dev: Move storage devices to src/dev/storage/
authorAndreas Sandberg <andreas.sandberg@arm.com>
Thu, 10 Dec 2015 10:35:23 +0000 (10:35 +0000)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Thu, 10 Dec 2015 10:35:23 +0000 (10:35 +0000)
Move the IDE controller and the disk implementations to
src/dev/storage.

--HG--
rename : src/dev/DiskImage.py => src/dev/storage/DiskImage.py
rename : src/dev/Ide.py => src/dev/storage/Ide.py
rename : src/dev/SimpleDisk.py => src/dev/storage/SimpleDisk.py
rename : src/dev/disk_image.cc => src/dev/storage/disk_image.cc
rename : src/dev/disk_image.hh => src/dev/storage/disk_image.hh
rename : src/dev/ide_atareg.h => src/dev/storage/ide_atareg.h
rename : src/dev/ide_ctrl.cc => src/dev/storage/ide_ctrl.cc
rename : src/dev/ide_ctrl.hh => src/dev/storage/ide_ctrl.hh
rename : src/dev/ide_disk.cc => src/dev/storage/ide_disk.cc
rename : src/dev/ide_disk.hh => src/dev/storage/ide_disk.hh
rename : src/dev/ide_wdcreg.h => src/dev/storage/ide_wdcreg.h
rename : src/dev/simple_disk.cc => src/dev/storage/simple_disk.cc
rename : src/dev/simple_disk.hh => src/dev/storage/simple_disk.hh

33 files changed:
src/dev/DiskImage.py [deleted file]
src/dev/Ide.py [deleted file]
src/dev/SConscript
src/dev/SimpleDisk.py [deleted file]
src/dev/alpha/backdoor.cc
src/dev/arm/ufs_device.hh
src/dev/disk_image.cc [deleted file]
src/dev/disk_image.hh [deleted file]
src/dev/ide_atareg.h [deleted file]
src/dev/ide_ctrl.cc [deleted file]
src/dev/ide_ctrl.hh [deleted file]
src/dev/ide_disk.cc [deleted file]
src/dev/ide_disk.hh [deleted file]
src/dev/ide_wdcreg.h [deleted file]
src/dev/simple_disk.cc [deleted file]
src/dev/simple_disk.hh [deleted file]
src/dev/sparc/iob.hh
src/dev/sparc/mm_disk.hh
src/dev/storage/DiskImage.py [new file with mode: 0644]
src/dev/storage/Ide.py [new file with mode: 0644]
src/dev/storage/SConscript [new file with mode: 0644]
src/dev/storage/SimpleDisk.py [new file with mode: 0644]
src/dev/storage/disk_image.cc [new file with mode: 0644]
src/dev/storage/disk_image.hh [new file with mode: 0644]
src/dev/storage/ide_atareg.h [new file with mode: 0644]
src/dev/storage/ide_ctrl.cc [new file with mode: 0644]
src/dev/storage/ide_ctrl.hh [new file with mode: 0644]
src/dev/storage/ide_disk.cc [new file with mode: 0644]
src/dev/storage/ide_disk.hh [new file with mode: 0644]
src/dev/storage/ide_wdcreg.h [new file with mode: 0644]
src/dev/storage/simple_disk.cc [new file with mode: 0644]
src/dev/storage/simple_disk.hh [new file with mode: 0644]
src/dev/virtio/block.hh

diff --git a/src/dev/DiskImage.py b/src/dev/DiskImage.py
deleted file mode 100644 (file)
index 38cc6e7..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright (c) 2005-2007 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Authors: Nathan Binkert
-
-from m5.SimObject import SimObject
-from m5.params import *
-class DiskImage(SimObject):
-    type = 'DiskImage'
-    abstract = True
-    cxx_header = "dev/disk_image.hh"
-    image_file = Param.String("disk image file")
-    read_only = Param.Bool(False, "read only image")
-
-class RawDiskImage(DiskImage):
-    type = 'RawDiskImage'
-    cxx_header = "dev/disk_image.hh"
-
-class CowDiskImage(DiskImage):
-    type = 'CowDiskImage'
-    cxx_header = "dev/disk_image.hh"
-    child = Param.DiskImage(RawDiskImage(read_only=True),
-                            "child image")
-    table_size = Param.Int(65536, "initial table size")
-    image_file = ""
diff --git a/src/dev/Ide.py b/src/dev/Ide.py
deleted file mode 100644 (file)
index 4d3da19..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-# Copyright (c) 2005-2007 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Authors: Nathan Binkert
-
-from m5.SimObject import SimObject
-from m5.params import *
-from PciDevice import PciDevice
-
-class IdeID(Enum): vals = ['master', 'slave']
-
-class IdeDisk(SimObject):
-    type = 'IdeDisk'
-    cxx_header = "dev/ide_disk.hh"
-    delay = Param.Latency('1us', "Fixed disk delay in microseconds")
-    driveID = Param.IdeID('master', "Drive ID")
-    image = Param.DiskImage("Disk image")
-
-class IdeController(PciDevice):
-    type = 'IdeController'
-    cxx_header = "dev/ide_ctrl.hh"
-    disks = VectorParam.IdeDisk("IDE disks attached to this controller")
-
-    VendorID = 0x8086
-    DeviceID = 0x7111
-    Command = 0x0
-    Status = 0x280
-    Revision = 0x0
-    ClassCode = 0x01
-    SubClassCode = 0x01
-    ProgIF = 0x85
-    BAR0 = 0x00000001
-    BAR1 = 0x00000001
-    BAR2 = 0x00000001
-    BAR3 = 0x00000001
-    BAR4 = 0x00000001
-    BAR5 = 0x00000001
-    InterruptLine = 0x1f
-    InterruptPin = 0x01
-    BAR0Size = '8B'
-    BAR1Size = '4B'
-    BAR2Size = '8B'
-    BAR3Size = '4B'
-    BAR4Size = '16B'
-
-    io_shift = Param.UInt32(0x0, "IO port shift");
-    ctrl_offset = Param.UInt32(0x0, "IDE disk control offset")
index 85bf839ec48dbfdef800b59bf895b9708f26eeda..2f3ec5d174c80ee74e6bce206c9cc5b1977e2532 100644 (file)
@@ -40,40 +40,24 @@ if env['TARGET_ISA'] == 'null':
     Return()
 
 SimObject('BadDevice.py')
-SimObject('DiskImage.py')
-SimObject('Ide.py')
 SimObject('Platform.py')
-SimObject('SimpleDisk.py')
 SimObject('Terminal.py')
 SimObject('Uart.py')
 
 Source('baddev.cc')
-Source('disk_image.cc')
 Source('dma_device.cc')
-Source('ide_ctrl.cc')
-Source('ide_disk.cc')
 Source('intel_8254_timer.cc')
 Source('mc146818.cc')
 Source('pixelpump.cc')
 Source('platform.cc')
 Source('ps2.cc')
-Source('simple_disk.cc')
 Source('terminal.cc')
 Source('uart.cc')
 Source('uart8250.cc')
 
-DebugFlag('DiskImageRead')
-DebugFlag('DiskImageWrite')
 DebugFlag('DMA')
-DebugFlag('IdeCtrl')
-DebugFlag('IdeDisk')
 DebugFlag('Intel8254Timer')
 DebugFlag('MC146818')
-DebugFlag('SimpleDisk')
-DebugFlag('SimpleDiskData')
 DebugFlag('Terminal')
 DebugFlag('TerminalVerbose')
 DebugFlag('Uart')
-
-CompoundFlag('DiskImageAll', [ 'DiskImageRead', 'DiskImageWrite' ])
-CompoundFlag('IdeAll', [ 'IdeCtrl', 'IdeDisk' ])
diff --git a/src/dev/SimpleDisk.py b/src/dev/SimpleDisk.py
deleted file mode 100644 (file)
index 88bf5db..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (c) 2005-2007 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Authors: Nathan Binkert
-
-from m5.SimObject import SimObject
-from m5.params import *
-from m5.proxy import *
-class SimpleDisk(SimObject):
-    type = 'SimpleDisk'
-    cxx_header = "dev/simple_disk.hh"
-    disk = Param.DiskImage("Disk Image")
-    system = Param.System(Parent.any, "System Pointer")
index ec5765673a943d9ea42b6c41792bdfddc63c7aef..93bfedf9d7ac44657ce0d016341ff5818d7a5601 100644 (file)
@@ -50,7 +50,7 @@
 #include "dev/alpha/tsunami_cchip.hh"
 #include "dev/alpha/tsunami_io.hh"
 #include "dev/platform.hh"
-#include "dev/simple_disk.hh"
+#include "dev/storage/simple_disk.hh"
 #include "dev/terminal.hh"
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"
index b0be55777af76a60f2165e83c0bc5873a3d68c78..435d5f59ff0784db1e2e7d45f2b546ca5ab9bfac 100644 (file)
 #include "debug/UFSHostDevice.hh"
 #include "dev/arm/abstract_nvm.hh"
 #include "dev/arm/base_gic.hh"
-#include "dev/disk_image.hh"
+#include "dev/storage/disk_image.hh"
 #include "dev/dma_device.hh"
 #include "dev/io_device.hh"
 #include "mem/packet.hh"
diff --git a/src/dev/disk_image.cc b/src/dev/disk_image.cc
deleted file mode 100644 (file)
index e490785..0000000
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Nathan Binkert
- */
-
-/** @file
- * Disk Image Definitions
- */
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-
-#include <cerrno>
-#include <cstring>
-#include <fstream>
-#include <string>
-
-#include "base/callback.hh"
-#include "base/misc.hh"
-#include "base/trace.hh"
-#include "debug/DiskImageRead.hh"
-#include "debug/DiskImageWrite.hh"
-#include "dev/disk_image.hh"
-#include "sim/byteswap.hh"
-#include "sim/sim_exit.hh"
-
-using namespace std;
-
-////////////////////////////////////////////////////////////////////////
-//
-// Raw Disk image
-//
-RawDiskImage::RawDiskImage(const Params* p)
-    : DiskImage(p), disk_size(0)
-{ open(p->image_file, p->read_only); }
-
-RawDiskImage::~RawDiskImage()
-{ close(); }
-
-void
-RawDiskImage::open(const string &filename, bool rd_only)
-{
-    if (!filename.empty()) {
-        initialized = true;
-        readonly = rd_only;
-        file = filename;
-
-        ios::openmode mode = ios::in | ios::binary;
-        if (!readonly)
-            mode |= ios::out;
-        stream.open(file.c_str(), mode);
-        if (!stream.is_open())
-            panic("Error opening %s", filename);
-    }
-}
-
-void
-RawDiskImage::close()
-{
-    stream.close();
-}
-
-std::streampos
-RawDiskImage::size() const
-{
-    if (disk_size == 0) {
-        if (!stream.is_open())
-            panic("file not open!\n");
-        stream.seekg(0, ios::end);
-        disk_size = stream.tellg();
-    }
-
-    return disk_size / SectorSize;
-}
-
-std::streampos
-RawDiskImage::read(uint8_t *data, std::streampos offset) const
-{
-    if (!initialized)
-        panic("RawDiskImage not initialized");
-
-    if (!stream.is_open())
-        panic("file not open!\n");
-
-    stream.seekg(offset * SectorSize, ios::beg);
-    if (!stream.good())
-        panic("Could not seek to location in file");
-
-    streampos pos = stream.tellg();
-    stream.read((char *)data, SectorSize);
-
-    DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
-    DDUMP(DiskImageRead, data, SectorSize);
-
-    return stream.tellg() - pos;
-}
-
-std::streampos
-RawDiskImage::write(const uint8_t *data, std::streampos offset)
-{
-    if (!initialized)
-        panic("RawDiskImage not initialized");
-
-    if (readonly)
-        panic("Cannot write to a read only disk image");
-
-    if (!stream.is_open())
-        panic("file not open!\n");
-
-    stream.seekp(offset * SectorSize, ios::beg);
-    if (!stream.good())
-        panic("Could not seek to location in file");
-
-    DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
-    DDUMP(DiskImageWrite, data, SectorSize);
-
-    streampos pos = stream.tellp();
-    stream.write((const char *)data, SectorSize);
-    return stream.tellp() - pos;
-}
-
-RawDiskImage *
-RawDiskImageParams::create()
-{
-    return new RawDiskImage(this);
-}
-
-////////////////////////////////////////////////////////////////////////
-//
-// Copy on Write Disk image
-//
-const uint32_t CowDiskImage::VersionMajor = 1;
-const uint32_t CowDiskImage::VersionMinor = 0;
-
-class CowDiskCallback : public Callback
-{
-  private:
-    CowDiskImage *image;
-
-  public:
-    CowDiskCallback(CowDiskImage *i) : image(i) {}
-    void process() { image->save(); delete this; }
-};
-
-CowDiskImage::CowDiskImage(const Params *p)
-    : DiskImage(p), filename(p->image_file), child(p->child), table(NULL)
-{
-    if (filename.empty()) {
-        initSectorTable(p->table_size);
-    } else {
-        if (!open(filename)) {
-            if (p->read_only)
-                fatal("could not open read-only file");
-            initSectorTable(p->table_size);
-        }
-
-        if (!p->read_only)
-            registerExitCallback(new CowDiskCallback(this));
-    }
-}
-
-CowDiskImage::~CowDiskImage()
-{
-    SectorTable::iterator i = table->begin();
-    SectorTable::iterator end = table->end();
-
-    while (i != end) {
-        delete (*i).second;
-        ++i;
-    }
-}
-
-void
-SafeRead(ifstream &stream, void *data, int count)
-{
-    stream.read((char *)data, count);
-    if (!stream.is_open())
-        panic("file not open");
-
-    if (stream.eof())
-        panic("premature end-of-file");
-
-    if (stream.bad() || stream.fail())
-        panic("error reading cowdisk image");
-}
-
-template<class T>
-void
-SafeRead(ifstream &stream, T &data)
-{
-    SafeRead(stream, &data, sizeof(data));
-}
-
-template<class T>
-void
-SafeReadSwap(ifstream &stream, T &data)
-{
-    SafeRead(stream, &data, sizeof(data));
-    data = letoh(data); //is this the proper byte order conversion?
-}
-
-bool
-CowDiskImage::open(const string &file)
-{
-    ifstream stream(file.c_str());
-    if (!stream.is_open())
-        return false;
-
-    if (stream.fail() || stream.bad())
-        panic("Error opening %s", file);
-
-    uint64_t magic;
-    SafeRead(stream, magic);
-
-    if (memcmp(&magic, "COWDISK!", sizeof(magic)) != 0)
-        panic("Could not open %s: Invalid magic", file);
-
-    uint32_t major, minor;
-    SafeReadSwap(stream, major);
-    SafeReadSwap(stream, minor);
-
-    if (major != VersionMajor && minor != VersionMinor)
-        panic("Could not open %s: invalid version %d.%d != %d.%d",
-              file, major, minor, VersionMajor, VersionMinor);
-
-    uint64_t sector_count;
-    SafeReadSwap(stream, sector_count);
-    table = new SectorTable(sector_count);
-
-
-    for (uint64_t i = 0; i < sector_count; i++) {
-        uint64_t offset;
-        SafeReadSwap(stream, offset);
-
-        Sector *sector = new Sector;
-        SafeRead(stream, sector, sizeof(Sector));
-
-        assert(table->find(offset) == table->end());
-        (*table)[offset] = sector;
-    }
-
-    stream.close();
-
-    initialized = true;
-    return true;
-}
-
-void
-CowDiskImage::initSectorTable(int hash_size)
-{
-    table = new SectorTable(hash_size);
-
-    initialized = true;
-}
-
-void
-SafeWrite(ofstream &stream, const void *data, int count)
-{
-    stream.write((const char *)data, count);
-    if (!stream.is_open())
-        panic("file not open");
-
-    if (stream.eof())
-        panic("premature end-of-file");
-
-    if (stream.bad() || stream.fail())
-        panic("error reading cowdisk image");
-}
-
-template<class T>
-void
-SafeWrite(ofstream &stream, const T &data)
-{
-    SafeWrite(stream, &data, sizeof(data));
-}
-
-template<class T>
-void
-SafeWriteSwap(ofstream &stream, const T &data)
-{
-    T swappeddata = letoh(data); //is this the proper byte order conversion?
-    SafeWrite(stream, &swappeddata, sizeof(data));
-}
-void
-CowDiskImage::save() const
-{
-    save(filename);
-}
-
-void
-CowDiskImage::save(const string &file) const
-{
-    if (!initialized)
-        panic("RawDiskImage not initialized");
-
-    ofstream stream(file.c_str());
-    if (!stream.is_open() || stream.fail() || stream.bad())
-        panic("Error opening %s", file);
-
-    uint64_t magic;
-    memcpy(&magic, "COWDISK!", sizeof(magic));
-    SafeWrite(stream, magic);
-
-    SafeWriteSwap(stream, (uint32_t)VersionMajor);
-    SafeWriteSwap(stream, (uint32_t)VersionMinor);
-    SafeWriteSwap(stream, (uint64_t)table->size());
-
-    uint64_t size = table->size();
-    SectorTable::iterator iter = table->begin();
-    SectorTable::iterator end = table->end();
-
-    for (uint64_t i = 0; i < size; i++) {
-        if (iter == end)
-            panic("Incorrect Table Size during save of COW disk image");
-
-        SafeWriteSwap(stream, (uint64_t)(*iter).first);
-        SafeWrite(stream, (*iter).second->data, sizeof(Sector));
-        ++iter;
-    }
-
-    stream.close();
-}
-
-void
-CowDiskImage::writeback()
-{
-    SectorTable::iterator i = table->begin();
-    SectorTable::iterator end = table->end();
-
-    while (i != end) {
-        child->write((*i).second->data, (*i).first);
-        ++i;
-    }
-}
-
-std::streampos
-CowDiskImage::size() const
-{ return child->size(); }
-
-std::streampos
-CowDiskImage::read(uint8_t *data, std::streampos offset) const
-{
-    if (!initialized)
-        panic("CowDiskImage not initialized");
-
-    if (offset > size())
-        panic("access out of bounds");
-
-    SectorTable::const_iterator i = table->find(offset);
-    if (i == table->end())
-        return child->read(data, offset);
-    else {
-        memcpy(data, (*i).second->data, SectorSize);
-        DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
-        DDUMP(DiskImageRead, data, SectorSize);
-        return SectorSize;
-    }
-}
-
-std::streampos
-CowDiskImage::write(const uint8_t *data, std::streampos offset)
-{
-    if (!initialized)
-        panic("RawDiskImage not initialized");
-
-    if (offset > size())
-        panic("access out of bounds");
-
-    SectorTable::iterator i = table->find(offset);
-    if (i == table->end()) {
-        Sector *sector = new Sector;
-        memcpy(sector, data, SectorSize);
-        table->insert(make_pair(offset, sector));
-    } else {
-        memcpy((*i).second->data, data, SectorSize);
-    }
-
-    DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
-    DDUMP(DiskImageWrite, data, SectorSize);
-
-    return SectorSize;
-}
-
-void
-CowDiskImage::serialize(CheckpointOut &cp) const
-{
-    string cowFilename = name() + ".cow";
-    SERIALIZE_SCALAR(cowFilename);
-    save(CheckpointIn::dir() + "/" + cowFilename);
-}
-
-void
-CowDiskImage::unserialize(CheckpointIn &cp)
-{
-    string cowFilename;
-    UNSERIALIZE_SCALAR(cowFilename);
-    cowFilename = cp.cptDir + "/" + cowFilename;
-    open(cowFilename);
-}
-
-CowDiskImage *
-CowDiskImageParams::create()
-{
-    return new CowDiskImage(this);
-}
diff --git a/src/dev/disk_image.hh b/src/dev/disk_image.hh
deleted file mode 100644 (file)
index fa25fc7..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Nathan Binkert
- */
-
-/** @file
- * Disk Image Interfaces
- */
-
-#ifndef __DISK_IMAGE_HH__
-#define __DISK_IMAGE_HH__
-
-#include <fstream>
-#include <unordered_map>
-
-#include "params/CowDiskImage.hh"
-#include "params/DiskImage.hh"
-#include "params/RawDiskImage.hh"
-#include "sim/sim_object.hh"
-
-#define SectorSize (512)
-
-/**
- * Basic interface for accessing a disk image.
- */
-class DiskImage : public SimObject
-{
-  protected:
-    bool initialized;
-
-  public:
-    typedef DiskImageParams Params;
-    DiskImage(const Params *p) : SimObject(p), initialized(false) {}
-    virtual ~DiskImage() {}
-
-    virtual std::streampos size() const = 0;
-
-    virtual std::streampos read(uint8_t *data,
-                                std::streampos offset) const = 0;
-    virtual std::streampos write(const uint8_t *data,
-                                 std::streampos offset) = 0;
-};
-
-/**
- * Specialization for accessing a raw disk image
- */
-class RawDiskImage : public DiskImage
-{
-  protected:
-    mutable std::fstream stream;
-    std::string file;
-    bool readonly;
-    mutable std::streampos disk_size;
-
-  public:
-    typedef RawDiskImageParams Params;
-    RawDiskImage(const Params *p);
-    ~RawDiskImage();
-
-    void close();
-    void open(const std::string &filename, bool rd_only = false);
-
-    virtual std::streampos size() const;
-
-    virtual std::streampos read(uint8_t *data, std::streampos offset) const;
-    virtual std::streampos write(const uint8_t *data, std::streampos offset);
-};
-
-/**
- * Specialization for accessing a copy-on-write disk image layer.
- * A copy-on-write(COW) layer must be stacked on top of another disk
- * image layer this layer can be another CowDiskImage, or a
- * RawDiskImage.
- *
- * This object is designed to provide a mechanism for persistant
- * changes to a main disk image, or to provide a place for temporary
- * changes to the image to take place that later may be thrown away.
- */
-class CowDiskImage : public DiskImage
-{
-  public:
-    static const uint32_t VersionMajor;
-    static const uint32_t VersionMinor;
-
-  protected:
-    struct Sector {
-        uint8_t data[SectorSize];
-    };
-    typedef std::unordered_map<uint64_t, Sector *> SectorTable;
-
-  protected:
-    std::string filename;
-    DiskImage *child;
-    SectorTable *table;
-
-  public:
-    typedef CowDiskImageParams Params;
-    CowDiskImage(const Params *p);
-    ~CowDiskImage();
-
-    void initSectorTable(int hash_size);
-    bool open(const std::string &file);
-    void save() const;
-    void save(const std::string &file) const;
-    void writeback();
-
-    void serialize(CheckpointOut &cp) const override;
-    void unserialize(CheckpointIn &cp) override;
-
-    std::streampos size() const override;
-
-    std::streampos read(uint8_t *data, std::streampos offset) const override;
-    std::streampos write(const uint8_t *data, std::streampos offset) override;
-};
-
-void SafeRead(std::ifstream &stream, void *data, int count);
-
-template<class T>
-void SafeRead(std::ifstream &stream, T &data);
-
-template<class T>
-void SafeReadSwap(std::ifstream &stream, T &data);
-
-void SafeWrite(std::ofstream &stream, const void *data, int count);
-
-template<class T>
-void SafeWrite(std::ofstream &stream, const T &data);
-
-template<class T>
-void SafeWriteSwap(std::ofstream &stream, const T &data);
-
-#endif // __DISK_IMAGE_HH__
diff --git a/src/dev/ide_atareg.h b/src/dev/ide_atareg.h
deleted file mode 100644 (file)
index d19a754..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/*     $OpenBSD: atareg.h,v 1.12 2004/09/24 07:15:22 grange Exp $      */
-/*     $NetBSD: atareg.h,v 1.5 1999/01/18 20:06:24 bouyer Exp $        */
-
-/*
- * Copyright (c) 1998, 2001 Manuel Bouyer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by Manuel Bouyer.
- * 4. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _DEV_ATA_ATAREG_H_
-#define _DEV_ATA_ATAREG_H_
-
-#if defined(__linux__)
-#include <endian.h>
-#elif defined(__sun)
-#include <sys/isa_defs.h>
-#else
-#include <machine/endian.h>
-#endif
-
-#ifdef LITTLE_ENDIAN
-#define ATA_BYTE_ORDER LITTLE_ENDIAN
-#elif defined(BIG_ENDIAN)
-#define ATA_BYTE_ORDER BIG_ENDIAN
-#elif defined(_LITTLE_ENDIAN)
-#define ATA_BYTE_ORDER 1
-#define LITTLE_ENDIAN 1
-#elif defined(_BIG_ENDIAN)
-#define ATA_BYTE_ORDER 0
-#define LITTLE_ENDIAN 1
-#else
-#error "No endianess defined"
-#endif
-
-/*
- * Drive parameter structure for ATA/ATAPI.
- * Bit fields: WDC_* : common to ATA/ATAPI
- *             ATA_* : ATA only
- *             ATAPI_* : ATAPI only.
- */
-struct ataparams {
-    /* drive info */
-    uint16_t   atap_config;            /* 0: general configuration */
-#define WDC_CFG_ATAPI_MASK             0xc000
-#define WDC_CFG_ATAPI                  0x8000
-#define ATA_CFG_REMOVABLE              0x0080
-#define ATA_CFG_FIXED                  0x0040
-#define ATAPI_CFG_TYPE_MASK            0x1f00
-#define ATAPI_CFG_TYPE(x)              (((x) & ATAPI_CFG_TYPE_MASK) >> 8)
-#define ATAPI_CFG_TYPE_DIRECT          0x00
-#define ATAPI_CFG_TYPE_SEQUENTIAL      0x01
-#define ATAPI_CFG_TYPE_CDROM           0x05
-#define ATAPI_CFG_TYPE_OPTICAL         0x07
-#define ATAPI_CFG_TYPE_NODEVICE                0x1F
-#define ATAPI_CFG_REMOV                        0x0080
-#define ATAPI_CFG_DRQ_MASK             0x0060
-#define ATAPI_CFG_STD_DRQ              0x0000
-#define ATAPI_CFG_IRQ_DRQ              0x0020
-#define ATAPI_CFG_ACCEL_DRQ            0x0040
-#define ATAPI_CFG_CMD_MASK             0x0003
-#define ATAPI_CFG_CMD_12               0x0000
-#define ATAPI_CFG_CMD_16               0x0001
-/* words 1-9 are ATA only */
-    uint16_t   atap_cylinders;         /* 1: # of non-removable cylinders */
-    uint16_t   __reserved1;
-    uint16_t   atap_heads;             /* 3: # of heads */
-    uint16_t   __retired1[2];          /* 4-5: # of unform. bytes/track */
-    uint16_t   atap_sectors;           /* 6: # of sectors */
-    uint16_t   __retired2[3];
-
-    uint8_t    atap_serial[20];        /* 10-19: serial number */
-    uint16_t   __retired3[2];
-    uint16_t   __obsolete1;
-    uint8_t    atap_revision[8];       /* 23-26: firmware revision */
-    uint8_t    atap_model[40];         /* 27-46: model number */
-    uint16_t   atap_multi;             /* 47: maximum sectors per irq (ATA) */
-    uint16_t   __reserved2;
-    uint8_t    atap_vendor;            /* 49: vendor  */
-    uint8_t    atap_capabilities1;     /* 49: capability flags */
-#define WDC_CAP_IORDY  0x0800
-#define WDC_CAP_IORDY_DSBL 0x0400
-#define WDC_CAP_LBA    0x0200
-#define WDC_CAP_DMA    0x0100
-#define ATA_CAP_STBY   0x2000
-#define ATAPI_CAP_INTERL_DMA   0x8000
-#define ATAPI_CAP_CMD_QUEUE    0x4000
-#define ATAPI_CAP_OVERLP       0x2000
-#define ATAPI_CAP_ATA_RST      0x1000
-    uint16_t   atap_capabilities2;     /* 50: capability flags (ATA) */
-#if ATA_BYTE_ORDER == LITTLE_ENDIAN
-    uint8_t    __junk2;
-    uint8_t    atap_oldpiotiming;      /* 51: old PIO timing mode */
-    uint8_t    __junk3;
-    uint8_t    atap_olddmatiming;      /* 52: old DMA timing mode (ATA) */
-#else
-    uint8_t    atap_oldpiotiming;      /* 51: old PIO timing mode */
-    uint8_t    __junk2;
-    uint8_t    atap_olddmatiming;      /* 52: old DMA timing mode (ATA) */
-    uint8_t    __junk3;
-#endif
-    uint16_t   atap_extensions;        /* 53: extensions supported */
-#define WDC_EXT_UDMA_MODES     0x0004
-#define WDC_EXT_MODES          0x0002
-#define WDC_EXT_GEOM           0x0001
-/* words 54-62 are ATA only */
-    uint16_t   atap_curcylinders;      /* 54: current logical cylinders */
-    uint16_t   atap_curheads;          /* 55: current logical heads */
-    uint16_t   atap_cursectors;        /* 56: current logical sectors/tracks */
-    uint16_t   atap_curcapacity[2];    /* 57-58: current capacity */
-    uint8_t    atap_curmulti;          /* 59: current multi-sector setting */
-    uint8_t    atap_curmulti_valid;    /* 59: current multi-sector setting */
-#define WDC_MULTI_VALID 0x0100
-#define WDC_MULTI_MASK  0x00ff
-    uint32_t   atap_capacity;  /* 60-61: total capacity (LBA only) */
-    uint16_t   __retired4;
-#if ATA_BYTE_ORDER == LITTLE_ENDIAN
-    uint8_t    atap_dmamode_supp;      /* 63: multiword DMA mode supported */
-    uint8_t    atap_dmamode_act;       /*     multiword DMA mode active */
-    uint8_t    atap_piomode_supp;      /* 64: PIO mode supported */
-    uint8_t    __junk4;
-#else
-    uint8_t    atap_dmamode_act;       /*     multiword DMA mode active */
-    uint8_t    atap_dmamode_supp;      /* 63: multiword DMA mode supported */
-    uint8_t    __junk4;
-    uint8_t    atap_piomode_supp;      /* 64: PIO mode supported */
-#endif
-    uint16_t   atap_dmatiming_mimi;    /* 65: minimum DMA cycle time */
-    uint16_t   atap_dmatiming_recom;   /* 66: recommended DMA cycle time */
-    uint16_t   atap_piotiming;         /* 67: mini PIO cycle time without FC */
-    uint16_t   atap_piotiming_iordy;   /* 68: mini PIO cycle time with IORDY FC */
-    uint16_t   __reserved3[2];
-/* words 71-72 are ATAPI only */
-    uint16_t   atap_pkt_br;            /* 71: time (ns) to bus release */
-    uint16_t   atap_pkt_bsyclr;        /* 72: tme to clear BSY after service */
-    uint16_t   __reserved4[2];
-    uint16_t   atap_queuedepth;        /* 75: */
-#define WDC_QUEUE_DEPTH_MASK 0x1f
-    uint16_t   atap_sata_caps;         /* 76: SATA capabilities */
-#define SATA_SIGNAL_GEN1       0x0002  /* SATA Gen-1 signaling speed */
-#define SATA_SIGNAL_GEN2       0x0004  /* SATA Gen-2 signaling speed */
-#define SATA_NATIVE_CMDQ       0x0100  /* native command queuing */
-#define SATA_HOST_PWR_MGMT     0x0200  /* power management (host) */
-    uint16_t   atap_sata_reserved;     /* 77: reserved */
-    uint16_t   atap_sata_features_supp;/* 78: SATA features supported */
-#define SATA_NONZERO_OFFSETS   0x0002  /* non-zero buffer offsets */
-#define SATA_DMA_SETUP_AUTO    0x0004  /* DMA setup auto-activate */
-#define SATA_DRIVE_PWR_MGMT    0x0008  /* power management (device) */
-    uint16_t   atap_sata_features_en;  /* 79: SATA features enabled */
-    uint16_t   atap_ata_major;         /* 80: Major version number */
-#define WDC_VER_ATA1   0x0002
-#define WDC_VER_ATA2   0x0004
-#define WDC_VER_ATA3   0x0008
-#define WDC_VER_ATA4   0x0010
-#define WDC_VER_ATA5   0x0020
-#define WDC_VER_ATA6   0x0040
-#define WDC_VER_ATA7   0x0080
-#define WDC_VER_ATA8   0x0100
-#define WDC_VER_ATA9   0x0200
-#define WDC_VER_ATA10  0x0400
-#define WDC_VER_ATA11  0x0800
-#define WDC_VER_ATA12  0x1000
-#define WDC_VER_ATA13  0x2000
-#define WDC_VER_ATA14  0x4000
-    uint16_t   atap_ata_minor;         /* 81: Minor version number */
-    uint16_t   atap_cmd_set1;          /* 82: command set supported */
-#define WDC_CMD1_NOP   0x4000
-#define WDC_CMD1_RB    0x2000
-#define WDC_CMD1_WB    0x1000
-#define WDC_CMD1_HPA   0x0400
-#define WDC_CMD1_DVRST 0x0200
-#define WDC_CMD1_SRV   0x0100
-#define WDC_CMD1_RLSE  0x0080
-#define WDC_CMD1_AHEAD 0x0040
-#define WDC_CMD1_CACHE 0x0020
-#define WDC_CMD1_PKT   0x0010
-#define WDC_CMD1_PM    0x0008
-#define WDC_CMD1_REMOV 0x0004
-#define WDC_CMD1_SEC   0x0002
-#define WDC_CMD1_SMART 0x0001
-    uint16_t   atap_cmd_set2;          /* 83: command set supported */
-#define ATAPI_CMD2_FCE 0x2000 /* Flush Cache Ext supported */
-#define ATAPI_CMD2_FC  0x1000 /* Flush Cache supported */
-#define ATAPI_CMD2_DCO 0x0800 /* Device Configuration Overlay supported */
-#define ATAPI_CMD2_48AD        0x0400 /* 48bit address supported */
-#define ATAPI_CMD2_AAM 0x0200 /* Automatic Acoustic Management supported */
-#define ATAPI_CMD2_SM  0x0100 /* Set Max security extension supported */
-#define ATAPI_CMD2_SF  0x0040 /* Set Features subcommand required */
-#define ATAPI_CMD2_PUIS        0x0020 /* Power up in standby supported */
-#define WDC_CMD2_RMSN  0x0010
-#define ATA_CMD2_APM   0x0008
-#define ATA_CMD2_CFA   0x0004
-#define ATA_CMD2_RWQ   0x0002
-#define WDC_CMD2_DM    0x0001 /* Download Microcode supported */
-    uint16_t   atap_cmd_ext;           /* 84: command/features supp. ext. */
-#define ATAPI_CMDE_MSER        0x0004 /* Media serial number supported */
-#define ATAPI_CMDE_TEST        0x0002 /* SMART self-test supported */
-#define ATAPI_CMDE_SLOG        0x0001 /* SMART error logging supported */
-    uint16_t   atap_cmd1_en;           /* 85: cmd/features enabled */
-/* bits are the same as atap_cmd_set1 */
-    uint16_t   atap_cmd2_en;           /* 86: cmd/features enabled */
-/* bits are the same as atap_cmd_set2 */
-    uint16_t   atap_cmd_def;           /* 87: cmd/features default */
-/* bits are NOT the same as atap_cmd_ext */
-#if ATA_BYTE_ORDER == LITTLE_ENDIAN
-    uint8_t    atap_udmamode_supp;     /* 88: Ultra-DMA mode supported */
-    uint8_t    atap_udmamode_act;      /*     Ultra-DMA mode active */
-#else
-    uint8_t    atap_udmamode_act;      /*     Ultra-DMA mode active */
-    uint8_t    atap_udmamode_supp;     /* 88: Ultra-DMA mode supported */
-#endif
-/* 89-92 are ATA-only */
-    uint16_t   atap_seu_time;          /* 89: Sec. Erase Unit compl. time */
-    uint16_t   atap_eseu_time;         /* 90: Enhanced SEU compl. time */
-    uint16_t   atap_apm_val;           /* 91: current APM value */
-    uint16_t   atap_mpasswd_rev;       /* 92: Master Password revision */
-    uint16_t   atap_hwreset_res;       /* 93: Hardware reset value */
-#define ATA_HWRES_CBLID    0x2000  /* CBLID above Vih */
-#define ATA_HWRES_D1_PDIAG 0x0800  /* Device 1 PDIAG detect OK */
-#define ATA_HWRES_D1_CSEL  0x0400  /* Device 1 used CSEL for address */
-#define ATA_HWRES_D1_JUMP  0x0200  /* Device 1 jumpered to address */
-#define ATA_HWRES_D0_SEL   0x0040  /* Device 0 responds when Dev 1 selected */
-#define ATA_HWRES_D0_DASP  0x0020  /* Device 0 DASP detect OK */
-#define ATA_HWRES_D0_PDIAG 0x0010  /* Device 0 PDIAG detect OK */
-#define ATA_HWRES_D0_DIAG  0x0008  /* Device 0 diag OK */
-#define ATA_HWRES_D0_CSEL  0x0004  /* Device 0 used CSEL for address */
-#define ATA_HWRES_D0_JUMP  0x0002  /* Device 0 jumpered to address */
-#if ATA_BYTE_ORDER == LITTLE_ENDIAN
-    uint8_t    atap_acoustic_val;      /* 94: Current acoustic level */
-    uint8_t    atap_acoustic_def;      /*     recommended level */
-#else
-    uint8_t    atap_acoustic_def;      /*     recommended level */
-    uint8_t    atap_acoustic_val;      /* 94: Current acoustic level */
-#endif
-    uint16_t   __reserved6[5];         /* 95-99: reserved */
-    uint16_t   atap_max_lba[4];        /* 100-103: Max. user LBA add */
-    uint16_t   __reserved7[23];        /* 104-126: reserved */
-    uint16_t   atap_rmsn_supp;         /* 127: remov. media status notif. */
-#define WDC_RMSN_SUPP_MASK 0x0003
-#define WDC_RMSN_SUPP 0x0001
-    uint16_t   atap_sec_st;            /* 128: security status */
-#define WDC_SEC_LEV_MAX        0x0100
-#define WDC_SEC_ESE_SUPP 0x0020
-#define WDC_SEC_EXP    0x0010
-#define WDC_SEC_FROZEN 0x0008
-#define WDC_SEC_LOCKED 0x0004
-#define WDC_SEC_EN     0x0002
-#define WDC_SEC_SUPP   0x0001
-    uint16_t   __reserved8[31];        /* 129-159: vendor specific */
-    uint16_t   atap_cfa_power;         /* 160: CFA powermode */
-#define ATAPI_CFA_MAX_MASK  0x0FFF
-#define ATAPI_CFA_MODE1_DIS 0x1000 /* CFA Mode 1 Disabled */
-#define ATAPI_CFA_MODE1_REQ 0x2000 /* CFA Mode 1 Required */
-#define ATAPI_CFA_WORD160   0x8000 /* Word 160 supported */
-    uint16_t   __reserved9[15];        /* 161-175: reserved for CFA */
-    uint8_t    atap_media_serial[60];  /* 176-205: media serial number */
-    uint16_t   __reserved10[49];       /* 206-254: reserved */
-#if ATA_BYTE_ORDER == LITTLE_ENDIAN
-    uint8_t    atap_signature;         /* 255: Signature */
-    uint8_t    atap_checksum;          /*      Checksum */
-#else
-    uint8_t    atap_checksum;          /*      Checksum */
-    uint8_t    atap_signature;         /* 255: Signature */
-#endif
-};
-
-#undef ATA_BYTE_ORDER
-#endif /* !_DEV_ATA_ATAREG_H_ */
diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc
deleted file mode 100644 (file)
index 3e60862..0000000
+++ /dev/null
@@ -1,649 +0,0 @@
-/*
- * 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.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Andrew Schultz
- *          Ali Saidi
- *          Miguel Serrano
- */
-
-#include <string>
-
-#include "cpu/intr_control.hh"
-#include "debug/IdeCtrl.hh"
-#include "dev/ide_ctrl.hh"
-#include "dev/ide_disk.hh"
-#include "mem/packet.hh"
-#include "mem/packet_access.hh"
-#include "params/IdeController.hh"
-#include "sim/byteswap.hh"
-
-// 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 {
-    BMICommand = 0x0,
-    BMIStatus = 0x2,
-    BMIDescTablePtr = 0x4
-};
-
-// PCI config space registers
-enum ConfRegOffset {
-    PrimaryTiming = 0x40,
-    SecondaryTiming = 0x42,
-    DeviceTiming = 0x44,
-    UDMAControl = 0x48,
-    UDMATiming = 0x4A,
-    IDEConfig = 0x54
-};
-
-static const uint16_t timeRegWithDecodeEn = 0x8000;
-
-IdeController::Channel::Channel(
-        string newName, Addr _cmdSize, Addr _ctrlSize) :
-    _name(newName),
-    cmdAddr(0), cmdSize(_cmdSize), ctrlAddr(0), ctrlSize(_ctrlSize),
-    master(NULL), slave(NULL), selected(NULL)
-{
-    memset(&bmiRegs, 0, sizeof(bmiRegs));
-    bmiRegs.status.dmaCap0 = 1;
-    bmiRegs.status.dmaCap1 = 1;
-}
-
-IdeController::Channel::~Channel()
-{
-}
-
-IdeController::IdeController(Params *p)
-    : 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),
-    ioShift(p->io_shift), ctrlOffset(p->ctrl_offset)
-{
-    if (params()->disks.size() > 3)
-        panic("IDE controllers support a maximum of 4 devices attached!\n");
-
-    // Assign the disks to channels
-    int numDisks = params()->disks.size();
-    if (numDisks > 0)
-        primary.master = params()->disks[0];
-    if (numDisks > 1)
-        primary.slave = params()->disks[1];
-    if (numDisks > 2)
-        secondary.master = params()->disks[2];
-    if (numDisks > 3)
-        secondary.slave = params()->disks[3];
-
-    for (int i = 0; i < params()->disks.size(); i++) {
-        params()->disks[i]->setController(this);
-    }
-    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
-IdeController::isDiskSelected(IdeDisk *diskPtr)
-{
-    return (primary.selected == diskPtr || secondary.selected == diskPtr);
-}
-
-void
-IdeController::intrPost()
-{
-    primary.bmiRegs.status.intStatus = 1;
-    PciDevice::intrPost();
-}
-
-void
-IdeController::setDmaComplete(IdeDisk *disk)
-{
-    Channel *channel;
-    if (disk == primary.master || disk == primary.slave) {
-        channel = &primary;
-    } else if (disk == secondary.master || disk == secondary.slave) {
-        channel = &secondary;
-    } else {
-        panic("Unable to find disk based on pointer %#x\n", disk);
-    }
-
-    channel->bmiRegs.command.startStop = 0;
-    channel->bmiRegs.status.active = 0;
-    channel->bmiRegs.status.intStatus = 1;
-}
-
-Tick
-IdeController::readConfig(PacketPtr pkt)
-{
-    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
-    if (offset < PCI_DEVICE_SPECIFIC) {
-        return PciDevice::readConfig(pkt);
-    }
-
-    switch (pkt->getSize()) {
-      case sizeof(uint8_t):
-        switch (offset) {
-          case DeviceTiming:
-            pkt->set<uint8_t>(deviceTiming);
-            break;
-          case UDMAControl:
-            pkt->set<uint8_t>(udmaControl);
-            break;
-          case PrimaryTiming + 1:
-            pkt->set<uint8_t>(bits(htole(primaryTiming), 15, 8));
-            break;
-          case SecondaryTiming + 1:
-            pkt->set<uint8_t>(bits(htole(secondaryTiming), 15, 8));
-            break;
-          case IDEConfig:
-            pkt->set<uint8_t>(bits(htole(ideConfig), 7, 0));
-            break;
-          case IDEConfig + 1:
-            pkt->set<uint8_t>(bits(htole(ideConfig), 15, 8));
-            break;
-          default:
-            panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
-                    offset);
-        }
-        DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", offset,
-                (uint32_t)pkt->get<uint8_t>());
-        break;
-      case sizeof(uint16_t):
-        switch (offset) {
-          case UDMAControl:
-            pkt->set<uint16_t>(udmaControl);
-            break;
-          case PrimaryTiming:
-            pkt->set<uint16_t>(primaryTiming);
-            break;
-          case SecondaryTiming:
-            pkt->set<uint16_t>(secondaryTiming);
-            break;
-          case UDMATiming:
-            pkt->set<uint16_t>(udmaTiming);
-            break;
-          case IDEConfig:
-            pkt->set<uint16_t>(ideConfig);
-            break;
-          default:
-            panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
-                    offset);
-        }
-        DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset,
-                (uint32_t)pkt->get<uint16_t>());
-        break;
-      case sizeof(uint32_t):
-        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;
-      default:
-        panic("invalid access size(?) for PCI configspace!\n");
-    }
-    pkt->makeAtomicResponse();
-    return configDelay;
-}
-
-
-Tick
-IdeController::writeConfig(PacketPtr pkt)
-{
-    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
-    if (offset < PCI_DEVICE_SPECIFIC) {
-        PciDevice::writeConfig(pkt);
-    } else {
-        switch (pkt->getSize()) {
-          case sizeof(uint8_t):
-            switch (offset) {
-              case DeviceTiming:
-                deviceTiming = pkt->get<uint8_t>();
-                break;
-              case UDMAControl:
-                udmaControl = pkt->get<uint8_t>();
-                break;
-              case IDEConfig:
-                replaceBits(ideConfig, 7, 0, pkt->get<uint8_t>());
-                break;
-              case IDEConfig + 1:
-                replaceBits(ideConfig, 15, 8, pkt->get<uint8_t>());
-                break;
-              default:
-                panic("Invalid PCI configuration write "
-                        "for size 1 offset: %#x!\n", offset);
-            }
-            DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n",
-                    offset, (uint32_t)pkt->get<uint8_t>());
-            break;
-          case sizeof(uint16_t):
-            switch (offset) {
-              case UDMAControl:
-                udmaControl = pkt->get<uint16_t>();
-                break;
-              case PrimaryTiming:
-                primaryTiming = pkt->get<uint16_t>();
-                break;
-              case SecondaryTiming:
-                secondaryTiming = pkt->get<uint16_t>();
-                break;
-              case UDMATiming:
-                udmaTiming = pkt->get<uint16_t>();
-                break;
-              case IDEConfig:
-                ideConfig = pkt->get<uint16_t>();
-                break;
-              default:
-                panic("Invalid PCI configuration write "
-                        "for size 2 offset: %#x!\n",
-                        offset);
-            }
-            DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n",
-                    offset, (uint32_t)pkt->get<uint16_t>());
-            break;
-          case sizeof(uint32_t):
-            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");
-        }
-        pkt->makeAtomicResponse();
-    }
-
-    /* Trap command register writes and enable IO/BM as appropriate as well as
-     * BARs. */
-    switch(offset) {
-      case PCI0_BASE_ADDR0:
-        if (BARAddrs[0] != 0)
-            primary.cmdAddr = BARAddrs[0];
-        break;
-
-      case PCI0_BASE_ADDR1:
-        if (BARAddrs[1] != 0)
-            primary.ctrlAddr = BARAddrs[1];
-        break;
-
-      case PCI0_BASE_ADDR2:
-        if (BARAddrs[2] != 0)
-            secondary.cmdAddr = BARAddrs[2];
-        break;
-
-      case PCI0_BASE_ADDR3:
-        if (BARAddrs[3] != 0)
-            secondary.ctrlAddr = BARAddrs[3];
-        break;
-
-      case PCI0_BASE_ADDR4:
-        if (BARAddrs[4] != 0)
-            bmiAddr = BARAddrs[4];
-        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;
-    }
-    return configDelay;
-}
-
-void
-IdeController::Channel::accessCommand(Addr offset,
-        int size, uint8_t *data, bool read)
-{
-    const Addr SelectOffset = 6;
-    const uint8_t SelectDevBit = 0x10;
-
-    if (!read && offset == SelectOffset)
-        select(*data & SelectDevBit);
-
-    if (selected == NULL) {
-        assert(size == sizeof(uint8_t));
-        *data = 0;
-    } else if (read) {
-        selected->readCommand(offset, size, data);
-    } else {
-        selected->writeCommand(offset, size, data);
-    }
-}
-
-void
-IdeController::Channel::accessControl(Addr offset,
-        int size, uint8_t *data, bool read)
-{
-    if (selected == NULL) {
-        assert(size == sizeof(uint8_t));
-        *data = 0;
-    } else if (read) {
-        selected->readControl(offset, size, data);
-    } else {
-        selected->writeControl(offset, size, data);
-    }
-}
-
-void
-IdeController::Channel::accessBMI(Addr offset,
-        int size, uint8_t *data, bool read)
-{
-    assert(offset + size <= sizeof(BMIRegs));
-    if (read) {
-        memcpy(data, (uint8_t *)&bmiRegs + offset, size);
-    } else {
-        switch (offset) {
-          case BMICommand:
-            {
-                if (size != sizeof(uint8_t))
-                    panic("Invalid BMIC write size: %x\n", size);
-
-                BMICommandReg oldVal = bmiRegs.command;
-                BMICommandReg newVal = *data;
-
-                // if a DMA transfer is in progress, R/W control cannot change
-                if (oldVal.startStop && oldVal.rw != newVal.rw)
-                    oldVal.rw = newVal.rw;
-
-                if (oldVal.startStop != newVal.startStop) {
-                    if (selected == NULL)
-                        panic("DMA start for disk which does not exist\n");
-
-                    if (oldVal.startStop) {
-                        DPRINTF(IdeCtrl, "Stopping DMA transfer\n");
-                        bmiRegs.status.active = 0;
-
-                        selected->abortDma();
-                    } else {
-                        DPRINTF(IdeCtrl, "Starting DMA transfer\n");
-                        bmiRegs.status.active = 1;
-
-                        selected->startDma(letoh(bmiRegs.bmidtp));
-                    }
-                }
-
-                bmiRegs.command = newVal;
-            }
-            break;
-          case BMIStatus:
-            {
-                if (size != sizeof(uint8_t))
-                    panic("Invalid BMIS write size: %x\n", size);
-
-                BMIStatusReg oldVal = bmiRegs.status;
-                BMIStatusReg newVal = *data;
-
-                // the BMIDEA bit is read only
-                newVal.active = oldVal.active;
-
-                // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
-                if ((oldVal.intStatus == 1) && (newVal.intStatus == 1)) {
-                    newVal.intStatus = 0; // clear the interrupt?
-                } 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 {
-                    uint8_t tmp = oldVal.dmaError;
-                    newVal.dmaError = tmp;
-                }
-
-                bmiRegs.status = newVal;
-            }
-            break;
-          case BMIDescTablePtr:
-            if (size != sizeof(uint32_t))
-                panic("Invalid BMIDTP write size: %x\n", size);
-            bmiRegs.bmidtp = htole(*(uint32_t *)data & ~0x3);
-            break;
-          default:
-            if (size != sizeof(uint8_t) && size != sizeof(uint16_t) &&
-                    size != sizeof(uint32_t))
-                panic("IDE controller write of invalid write size: %x\n", size);
-            memcpy((uint8_t *)&bmiRegs + offset, data, size);
-        }
-    }
-}
-
-void
-IdeController::dispatchAccess(PacketPtr pkt, bool read)
-{
-    if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4)
-         panic("Bad IDE read size: %d\n", pkt->getSize());
-
-    if (!ioEnabled) {
-        pkt->makeAtomicResponse();
-        DPRINTF(IdeCtrl, "io not enabled\n");
-        return;
-    }
-
-    Addr addr = pkt->getAddr();
-    int size = pkt->getSize();
-    uint8_t *dataPtr = pkt->getPtr<uint8_t>();
-
-    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)) {
-        addr -= secondary.cmdAddr;
-        secondary.accessCommand(addr, size, dataPtr, read);
-    } else if (addr >= secondary.ctrlAddr &&
-               addr < (secondary.ctrlAddr + secondary.ctrlSize)) {
-        addr -= secondary.ctrlAddr;
-        secondary.accessControl(addr, size, dataPtr, read);
-    } else if (addr >= bmiAddr && addr < (bmiAddr + bmiSize)) {
-        if (!read && !bmEnabled)
-            return;
-        addr -= bmiAddr;
-        if (addr < sizeof(Channel::BMIRegs)) {
-            primary.accessBMI(addr, size, dataPtr, read);
-        } else {
-            addr -= sizeof(Channel::BMIRegs);
-            secondary.accessBMI(addr, size, dataPtr, read);
-        }
-    } else {
-        panic("IDE controller access to invalid address: %#x\n", addr);
-    }
-
-#ifndef NDEBUG
-    uint32_t data;
-    if (pkt->getSize() == 1)
-        data = pkt->get<uint8_t>();
-    else if (pkt->getSize() == 2)
-        data = pkt->get<uint16_t>();
-    else
-        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();
-}
-
-Tick
-IdeController::read(PacketPtr pkt)
-{
-    dispatchAccess(pkt, true);
-    return pioDelay;
-}
-
-Tick
-IdeController::write(PacketPtr pkt)
-{
-    dispatchAccess(pkt, false);
-    return pioDelay;
-}
-
-void
-IdeController::serialize(CheckpointOut &cp) const
-{
-    // Serialize the PciDevice base class
-    PciDevice::serialize(cp);
-
-    // Serialize channels
-    primary.serialize("primary", cp);
-    secondary.serialize("secondary", cp);
-
-    // Serialize config registers
-    SERIALIZE_SCALAR(primaryTiming);
-    SERIALIZE_SCALAR(secondaryTiming);
-    SERIALIZE_SCALAR(deviceTiming);
-    SERIALIZE_SCALAR(udmaControl);
-    SERIALIZE_SCALAR(udmaTiming);
-    SERIALIZE_SCALAR(ideConfig);
-
-    // Serialize internal state
-    SERIALIZE_SCALAR(ioEnabled);
-    SERIALIZE_SCALAR(bmEnabled);
-    SERIALIZE_SCALAR(bmiAddr);
-    SERIALIZE_SCALAR(bmiSize);
-}
-
-void
-IdeController::Channel::serialize(const std::string &base,
-                                  CheckpointOut &cp) const
-{
-    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(cp, base + ".bmiRegs.command", command);
-    paramOut(cp, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
-    uint8_t status = bmiRegs.status;
-    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(CheckpointIn &cp)
-{
-    // Unserialize the PciDevice base class
-    PciDevice::unserialize(cp);
-
-    // Unserialize channels
-    primary.unserialize("primary", cp);
-    secondary.unserialize("secondary", cp);
-
-    // Unserialize config registers
-    UNSERIALIZE_SCALAR(primaryTiming);
-    UNSERIALIZE_SCALAR(secondaryTiming);
-    UNSERIALIZE_SCALAR(deviceTiming);
-    UNSERIALIZE_SCALAR(udmaControl);
-    UNSERIALIZE_SCALAR(udmaTiming);
-    UNSERIALIZE_SCALAR(ideConfig);
-
-    // Unserialize internal state
-    UNSERIALIZE_SCALAR(ioEnabled);
-    UNSERIALIZE_SCALAR(bmEnabled);
-    UNSERIALIZE_SCALAR(bmiAddr);
-    UNSERIALIZE_SCALAR(bmiSize);
-}
-
-void
-IdeController::Channel::unserialize(const std::string &base, CheckpointIn &cp)
-{
-    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, base +".bmiRegs.command", command);
-    bmiRegs.command = command;
-    paramIn(cp, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
-    uint8_t status;
-    paramIn(cp, base + ".bmiRegs.status", status);
-    bmiRegs.status = status;
-    paramIn(cp, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
-    paramIn(cp, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
-    paramIn(cp, base + ".selectBit", selectBit);
-    select(selectBit);
-}
-
-IdeController *
-IdeControllerParams::create()
-{
-    return new IdeController(this);
-}
diff --git a/src/dev/ide_ctrl.hh b/src/dev/ide_ctrl.hh
deleted file mode 100644 (file)
index c6c4bee..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Andrew Schultz
- *          Miguel Serrano
- */
-
-/** @file
- * Simple PCI IDE controller with bus mastering capability and UDMA
- * modeled after controller in the Intel PIIX4 chip
- */
-
-#ifndef __IDE_CTRL_HH__
-#define __IDE_CTRL_HH__
-
-#include "base/bitunion.hh"
-#include "dev/io_device.hh"
-#include "dev/pci/device.hh"
-#include "params/IdeController.hh"
-
-class IdeDisk;
-
-/**
- * Device model for an Intel PIIX4 IDE controller
- */
-
-class IdeController : public PciDevice
-{
-  private:
-    // Bus master IDE status register bit fields
-    BitUnion8(BMIStatusReg)
-        Bitfield<6> dmaCap0;
-        Bitfield<5> dmaCap1;
-        Bitfield<2> intStatus;
-        Bitfield<1> dmaError;
-        Bitfield<0> active;
-    EndBitUnion(BMIStatusReg)
-
-    BitUnion8(BMICommandReg)
-        Bitfield<3> rw;
-        Bitfield<0> startStop;
-    EndBitUnion(BMICommandReg)
-
-    struct Channel
-    {
-        std::string _name;
-
-        const std::string
-        name()
-        {
-            return _name;
-        }
-
-        /** Command and control block registers */
-        Addr cmdAddr, cmdSize, ctrlAddr, ctrlSize;
-
-        /** Registers used for bus master interface */
-        struct BMIRegs
-        {
-            BMICommandReg command;
-            uint8_t reserved0;
-            BMIStatusReg status;
-            uint8_t reserved1;
-            uint32_t bmidtp;
-        } bmiRegs;
-
-        /** IDE disks connected to this controller */
-        IdeDisk *master, *slave;
-
-        /** Currently selected disk */
-        IdeDisk *selected;
-
-        bool selectBit;
-
-        void
-        select(bool selSlave)
-        {
-            selectBit = selSlave;
-            selected = selectBit ? slave : master;
-        }
-
-        void accessCommand(Addr offset, int size, uint8_t *data, bool read);
-        void accessControl(Addr offset, int size, uint8_t *data, bool read);
-        void accessBMI(Addr offset, int size, uint8_t *data, bool read);
-
-        Channel(std::string newName, Addr _cmdSize, Addr _ctrlSize);
-        ~Channel();
-
-        void serialize(const std::string &base, std::ostream &os) const;
-        void unserialize(const std::string &base, CheckpointIn &cp);
-    };
-
-    Channel primary;
-    Channel secondary;
-
-    /** Bus master interface (BMI) registers */
-    Addr bmiAddr, bmiSize;
-
-    /** Registers used in device specific PCI configuration */
-    uint16_t primaryTiming, secondaryTiming;
-    uint8_t deviceTiming;
-    uint8_t udmaControl;
-    uint16_t udmaTiming;
-    uint16_t ideConfig;
-
-    // Internal management variables
-    bool ioEnabled;
-    bool bmEnabled;
-
-    uint32_t ioShift, ctrlOffset;
-
-    void dispatchAccess(PacketPtr pkt, bool read);
-
-  public:
-    typedef IdeControllerParams Params;
-    const Params *params() const { return (const Params *)_params; }
-    IdeController(Params *p);
-
-    /** See if a disk is selected based on its pointer */
-    bool isDiskSelected(IdeDisk *diskPtr);
-
-    void intrPost();
-
-    Tick writeConfig(PacketPtr pkt) override;
-    Tick readConfig(PacketPtr pkt) override;
-
-    void setDmaComplete(IdeDisk *disk);
-
-    Tick read(PacketPtr pkt) override;
-    Tick write(PacketPtr pkt) override;
-
-    void serialize(CheckpointOut &cp) const override;
-    void unserialize(CheckpointIn &cp) override;
-};
-#endif // __IDE_CTRL_HH_
diff --git a/src/dev/ide_disk.cc b/src/dev/ide_disk.cc
deleted file mode 100644 (file)
index 2c8dfce..0000000
+++ /dev/null
@@ -1,1202 +0,0 @@
-/*
- * 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.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Andrew Schultz
- *          Ali Saidi
- */
-
-/** @file
- * Device model implementation for an IDE disk
- */
-
-#include <cerrno>
-#include <cstring>
-#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_ctrl.hh"
-#include "dev/ide_disk.hh"
-#include "sim/core.hh"
-#include "sim/sim_object.hh"
-
-using namespace std;
-using namespace TheISA;
-
-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(p->driveID);
-
-    // fill out the drive ID structure
-    memset(&driveID, 0, sizeof(struct ataparams));
-
-    // Calculate LBA and C/H/S values
-    uint16_t cylinders;
-    uint8_t heads;
-    uint8_t sectors;
-
-    uint32_t lba_size = image->size();
-    if (lba_size >= 16383*16*63) {
-        cylinders = 16383;
-        heads = 16;
-        sectors = 63;
-    } else {
-        if (lba_size >= 63)
-            sectors = 63;
-        else if (lba_size == 0)
-            panic("Bad IDE image size: 0\n");
-        else
-            sectors = lba_size;
-
-        if ((lba_size / sectors) >= 16)
-            heads = 16;
-        else
-            heads = (lba_size / sectors);
-
-        cylinders = lba_size / (heads * sectors);
-    }
-
-    // Setup the model name
-    strncpy((char *)driveID.atap_model, "5MI EDD si k",
-            sizeof(driveID.atap_model));
-    // Set the maximum multisector transfer size
-    driveID.atap_multi = MAX_MULTSECT;
-    // IORDY supported, IORDY disabled, LBA enabled, DMA enabled
-    driveID.atap_capabilities1 = 0x7;
-    // UDMA support, EIDE support
-    driveID.atap_extensions = 0x6;
-    // Setup default C/H/S settings
-    driveID.atap_cylinders = cylinders;
-    driveID.atap_sectors = sectors;
-    driveID.atap_heads = heads;
-    // Setup the current multisector transfer size
-    driveID.atap_curmulti = MAX_MULTSECT;
-    driveID.atap_curmulti_valid = 0x1;
-    // Number of sectors on disk
-    driveID.atap_capacity = lba_size;
-    // Multiword DMA mode 2 and below supported
-    driveID.atap_dmamode_supp = 0x4;
-    // Set PIO mode 4 and 3 supported
-    driveID.atap_piomode_supp = 0x3;
-    // Set DMA mode 4 and below supported
-    driveID.atap_udmamode_supp = 0x1f;
-    // Statically set hardware config word
-    driveID.atap_hwreset_res = 0x4001;
-
-    //arbitrary for now...
-    driveID.atap_ata_major = WDC_VER_ATA7;
-}
-
-IdeDisk::~IdeDisk()
-{
-    // destroy the data buffer
-    delete [] dataBuffer;
-}
-
-void
-IdeDisk::reset(int id)
-{
-    // initialize the data buffer and shadow registers
-    dataBuffer = new uint8_t[MAX_DMA_SIZE];
-
-    memset(dataBuffer, 0, MAX_DMA_SIZE);
-    memset(&cmdReg, 0, sizeof(CommandReg_t));
-    memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
-
-    curPrdAddr = 0;
-    curSector = 0;
-    cmdBytes = 0;
-    cmdBytesLeft = 0;
-    drqBytesLeft = 0;
-    dmaRead = false;
-    intrPending = false;
-    dmaAborted = false;
-
-    // set the device state to idle
-    dmaState = Dma_Idle;
-
-    if (id == DEV0) {
-        devState = Device_Idle_S;
-        devID = DEV0;
-    } else if (id == DEV1) {
-        devState = Device_Idle_NS;
-        devID = DEV1;
-    } else {
-        panic("Invalid device ID: %#x\n", id);
-    }
-
-    // set the device ready bit
-    status = STATUS_DRDY_BIT;
-
-    /* The error register must be set to 0x1 on start-up to
-       indicate that no diagnostic error was detected */
-    cmdReg.error = 0x1;
-}
-
-////
-// Utility functions
-////
-
-bool
-IdeDisk::isDEVSelect()
-{
-    return ctrl->isDiskSelected(this);
-}
-
-Addr
-IdeDisk::pciToDma(Addr pciAddr)
-{
-    if (ctrl)
-        return ctrl->pciToDma(pciAddr);
-    else
-        panic("Access to unset controller!\n");
-}
-
-////
-// Device registers read/write
-////
-
-void
-IdeDisk::readCommand(const Addr offset, int size, uint8_t *data)
-{
-    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 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("Invalid IDE command register offset: %#x\n", offset);
-    }
-    DPRINTF(IdeDisk, "Read to disk at offset: %#x data %#x\n", offset, *data);
-}
-
-void
-IdeDisk::readControl(const Addr offset, int size, uint8_t *data)
-{
-    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);
-}
-
-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 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("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);
-}
-
-////
-// Perform DMA transactions
-////
-
-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);
-
-    if (ctrl->dmaPending() || ctrl->drainState() != DrainState::Running) {
-        schedule(dmaTransferEvent, curTick() + DMA_BACKOFF_PERIOD);
-        return;
-    } else
-        ctrl->dmaRead(curPrdAddr, sizeof(PrdEntry_t), &dmaPrdReadEvent,
-                (uint8_t*)&curPrd.entry);
-}
-
-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",
-            curPrd.getBaseAddr(), pciToDma(curPrd.getBaseAddr()),
-            curPrd.getByteCount(), (cmdBytesLeft/SectorSize),
-            curPrd.getEOT(), curSector);
-
-    // the prd pointer has already been translated, so just do an increment
-    curPrdAddr = curPrdAddr + sizeof(PrdEntry_t);
-
-    if (dmaRead)
-        doDmaDataRead();
-    else
-        doDmaDataWrite();
-}
-
-void
-IdeDisk::doDmaDataRead()
-{
-    /** @todo we need to figure out what the delay actually will be */
-    Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
-
-    DPRINTF(IdeDisk, "doDmaRead, diskDelay: %d totalDiskDelay: %d\n",
-            diskDelay, totalDiskDelay);
-
-    schedule(dmaReadWaitEvent, curTick() + totalDiskDelay);
-}
-
-void
-IdeDisk::regStats()
-{
-    using namespace Stats;
-    dmaReadFullPages
-        .name(name() + ".dma_read_full_pages")
-        .desc("Number of full page size DMA reads (not PRD).")
-        ;
-    dmaReadBytes
-        .name(name() + ".dma_read_bytes")
-        .desc("Number of bytes transfered via DMA reads (not PRD).")
-        ;
-    dmaReadTxs
-        .name(name() + ".dma_read_txs")
-        .desc("Number of DMA read transactions (not PRD).")
-        ;
-
-    dmaWriteFullPages
-        .name(name() + ".dma_write_full_pages")
-        .desc("Number of full page size DMA writes.")
-        ;
-    dmaWriteBytes
-        .name(name() + ".dma_write_bytes")
-        .desc("Number of bytes transfered via DMA writes.")
-        ;
-    dmaWriteTxs
-        .name(name() + ".dma_write_txs")
-        .desc("Number of DMA write transactions.")
-        ;
-}
-
-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
-        memset(dataBuffer, 0, MAX_DMA_SIZE);
-        dmaReadCG = new ChunkGenerator(curPrd.getBaseAddr(),
-                curPrd.getByteCount(), TheISA::PageBytes);
-
-    }
-    if (ctrl->dmaPending() || ctrl->drainState() != DrainState::Running) {
-        schedule(dmaReadWaitEvent, curTick() + DMA_BACKOFF_PERIOD);
-        return;
-    } else if (!dmaReadCG->done()) {
-        assert(dmaReadCG->complete() < MAX_DMA_SIZE);
-        ctrl->dmaRead(pciToDma(dmaReadCG->addr()), dmaReadCG->size(),
-                &dmaReadWaitEvent, dataBuffer + dmaReadCG->complete());
-        dmaReadBytes += dmaReadCG->size();
-        dmaReadTxs++;
-        if (dmaReadCG->size() == TheISA::PageBytes)
-            dmaReadFullPages++;
-        dmaReadCG->next();
-    } else {
-        assert(dmaReadCG->done());
-        delete dmaReadCG;
-        dmaReadCG = NULL;
-        dmaReadDone();
-    }
-}
-
-void
-IdeDisk::dmaReadDone()
-{
-    uint32_t bytesWritten = 0;
-
-    // write the data to the disk image
-    for (bytesWritten = 0; bytesWritten < curPrd.getByteCount();
-         bytesWritten += SectorSize) {
-
-        cmdBytesLeft -= SectorSize;
-        writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten));
-    }
-
-    // check for the EOT
-    if (curPrd.getEOT()) {
-        assert(cmdBytesLeft == 0);
-        dmaState = Dma_Idle;
-        updateState(ACT_DMA_DONE);
-    } else {
-        doDmaTransfer();
-    }
-}
-
-void
-IdeDisk::doDmaDataWrite()
-{
-    /** @todo we need to figure out what the delay actually will be */
-    Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
-    uint32_t bytesRead = 0;
-
-    DPRINTF(IdeDisk, "doDmaWrite, diskDelay: %d totalDiskDelay: %d\n",
-            diskDelay, totalDiskDelay);
-
-    memset(dataBuffer, 0, MAX_DMA_SIZE);
-    assert(cmdBytesLeft <= MAX_DMA_SIZE);
-    while (bytesRead < curPrd.getByteCount()) {
-        readDisk(curSector++, (uint8_t *)(dataBuffer + bytesRead));
-        bytesRead += SectorSize;
-        cmdBytesLeft -= SectorSize;
-    }
-    DPRINTF(IdeDisk, "doDmaWrite, bytesRead: %d cmdBytesLeft: %d\n",
-            bytesRead, cmdBytesLeft);
-
-    schedule(dmaWriteWaitEvent, curTick() + totalDiskDelay);
-}
-
-void
-IdeDisk::doDmaWrite()
-{
-    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(),
-                curPrd.getByteCount(), TheISA::PageBytes);
-    }
-    if (ctrl->dmaPending() || ctrl->drainState() != DrainState::Running) {
-        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;
-        dmaWriteDone();
-    }
-}
-
-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);
-        dmaState = Dma_Idle;
-        updateState(ACT_DMA_DONE);
-    } else {
-        doDmaTransfer();
-    }
-}
-
-////
-// Disk utility routines
-///
-
-void
-IdeDisk::readDisk(uint32_t sector, uint8_t *data)
-{
-    uint32_t bytesRead = image->read(data, sector);
-
-    if (bytesRead != SectorSize)
-        panic("Can't read from %s. Only %d of %d read. errno=%d\n",
-              name(), bytesRead, SectorSize, errno);
-}
-
-void
-IdeDisk::writeDisk(uint32_t sector, uint8_t *data)
-{
-    uint32_t bytesWritten = image->write(data, sector);
-
-    if (bytesWritten != SectorSize)
-        panic("Can't write to %s. Only %d of %d written. errno=%d\n",
-              name(), bytesWritten, SectorSize, errno);
-}
-
-////
-// Setup and handle commands
-////
-
-void
-IdeDisk::startDma(const uint32_t &prdTableBase)
-{
-    if (dmaState != Dma_Start)
-        panic("Inconsistent DMA state, should be in Dma_Start!\n");
-
-    if (devState != Transfer_Data_Dma)
-        panic("Inconsistent device state for DMA start!\n");
-
-    // PRD base address is given by bits 31:2
-    curPrdAddr = pciToDma((Addr)(prdTableBase & ~ULL(0x3)));
-
-    dmaState = Dma_Transfer;
-
-    // schedule dma transfer (doDmaTransfer)
-    schedule(dmaTransferEvent, curTick() + 1);
-}
-
-void
-IdeDisk::abortDma()
-{
-    if (dmaState == Dma_Idle)
-        panic("Inconsistent DMA state, should be Start or Transfer!");
-
-    if (devState != Transfer_Data_Dma && devState != Prepare_Data_Dma)
-        panic("Inconsistent device state, should be Transfer or Prepare!\n");
-
-    updateState(ACT_CMD_ERROR);
-}
-
-void
-IdeDisk::startCommand()
-{
-    DevAction_t action = ACT_NONE;
-    uint32_t size = 0;
-    dmaRead = false;
-
-    // Decode commands
-    switch (cmdReg.command) {
-        // Supported non-data commands
-      case WDSF_READ_NATIVE_MAX:
-        size = (uint32_t)image->size() - 1;
-        cmdReg.sec_num = (size & 0xff);
-        cmdReg.cyl_low = ((size & 0xff00) >> 8);
-        cmdReg.cyl_high = ((size & 0xff0000) >> 16);
-        cmdReg.head = ((size & 0xf000000) >> 24);
-
-        devState = Command_Execution;
-        action = ACT_CMD_COMPLETE;
-        break;
-
-      case WDCC_RECAL:
-      case WDCC_IDP:
-      case WDCC_STANDBY_IMMED:
-      case WDCC_FLUSHCACHE:
-      case WDSF_VERIFY:
-      case WDSF_SEEK:
-      case SET_FEATURES:
-      case WDCC_SETMULTI:
-      case WDCC_IDLE:
-        devState = Command_Execution;
-        action = ACT_CMD_COMPLETE;
-        break;
-
-        // Supported PIO data-in commands
-      case WDCC_IDENTIFY:
-        cmdBytes = cmdBytesLeft = sizeof(struct ataparams);
-        devState = Prepare_Data_In;
-        action = ACT_DATA_READY;
-        break;
-
-      case WDCC_READMULTI:
-      case WDCC_READ:
-        if (!(cmdReg.drive & DRIVE_LBA_BIT))
-            panic("Attempt to perform CHS access, only supports LBA\n");
-
-        if (cmdReg.sec_count == 0)
-            cmdBytes = cmdBytesLeft = (256 * SectorSize);
-        else
-            cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
-
-        curSector = getLBABase();
-
-        /** @todo make this a scheduled event to simulate disk delay */
-        devState = Prepare_Data_In;
-        action = ACT_DATA_READY;
-        break;
-
-        // Supported PIO data-out commands
-      case WDCC_WRITEMULTI:
-      case WDCC_WRITE:
-        if (!(cmdReg.drive & DRIVE_LBA_BIT))
-            panic("Attempt to perform CHS access, only supports LBA\n");
-
-        if (cmdReg.sec_count == 0)
-            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;
-        action = ACT_DATA_READY;
-        break;
-
-        // Supported DMA commands
-      case WDCC_WRITEDMA:
-        dmaRead = true;  // a write to the disk is a DMA read from memory
-      case WDCC_READDMA:
-        if (!(cmdReg.drive & DRIVE_LBA_BIT))
-            panic("Attempt to perform CHS access, only supports LBA\n");
-
-        if (cmdReg.sec_count == 0)
-            cmdBytes = cmdBytesLeft = (256 * SectorSize);
-        else
-            cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
-        DPRINTF(IdeDisk, "Setting cmdBytesLeft to %d in readdma\n", cmdBytesLeft);
-
-        curSector = getLBABase();
-
-        devState = Prepare_Data_Dma;
-        action = ACT_DMA_READY;
-        break;
-
-      default:
-        panic("Unsupported ATA command: %#x\n", cmdReg.command);
-    }
-
-    if (action != ACT_NONE) {
-        // set the BSY bit
-        status |= STATUS_BSY_BIT;
-        // clear the DRQ bit
-        status &= ~STATUS_DRQ_BIT;
-        // clear the DF bit
-        status &= ~STATUS_DF_BIT;
-
-        updateState(action);
-    }
-}
-
-////
-// Handle setting and clearing interrupts
-////
-
-void
-IdeDisk::intrPost()
-{
-    DPRINTF(IdeDisk, "Posting Interrupt\n");
-    if (intrPending)
-        panic("Attempt to post an interrupt with one pending\n");
-
-    intrPending = true;
-
-    // talk to controller to set interrupt
-    if (ctrl) {
-        ctrl->intrPost();
-    }
-}
-
-void
-IdeDisk::intrClear()
-{
-    DPRINTF(IdeDisk, "Clearing Interrupt\n");
-    if (!intrPending)
-        panic("Attempt to clear a non-pending interrupt\n");
-
-    intrPending = false;
-
-    // talk to controller to clear interrupt
-    if (ctrl)
-        ctrl->intrClear();
-}
-
-////
-// Manage the device internal state machine
-////
-
-void
-IdeDisk::updateState(DevAction_t action)
-{
-    switch (devState) {
-      case Device_Srst:
-        if (action == ACT_SRST_SET) {
-            // set the BSY bit
-            status |= STATUS_BSY_BIT;
-        } else if (action == ACT_SRST_CLEAR) {
-            // clear the BSY bit
-            status &= ~STATUS_BSY_BIT;
-
-            // reset the device state
-            reset(devID);
-        }
-        break;
-
-      case Device_Idle_S:
-        if (action == ACT_SELECT_WRITE && !isDEVSelect()) {
-            devState = Device_Idle_NS;
-        } else if (action == ACT_CMD_WRITE) {
-            startCommand();
-        }
-
-        break;
-
-      case Device_Idle_SI:
-        if (action == ACT_SELECT_WRITE && !isDEVSelect()) {
-            devState = Device_Idle_NS;
-            intrClear();
-        } else if (action == ACT_STAT_READ || isIENSet()) {
-            devState = Device_Idle_S;
-            intrClear();
-        } else if (action == ACT_CMD_WRITE) {
-            intrClear();
-            startCommand();
-        }
-
-        break;
-
-      case Device_Idle_NS:
-        if (action == ACT_SELECT_WRITE && isDEVSelect()) {
-            if (!isIENSet() && intrPending) {
-                devState = Device_Idle_SI;
-                intrPost();
-            }
-            if (isIENSet() || !intrPending) {
-                devState = Device_Idle_S;
-            }
-        }
-        break;
-
-      case Command_Execution:
-        if (action == ACT_CMD_COMPLETE) {
-            // clear the BSY bit
-            setComplete();
-
-            if (!isIENSet()) {
-                devState = Device_Idle_SI;
-                intrPost();
-            } else {
-                devState = Device_Idle_S;
-            }
-        }
-        break;
-
-      case Prepare_Data_In:
-        if (action == ACT_CMD_ERROR) {
-            // clear the BSY bit
-            setComplete();
-
-            if (!isIENSet()) {
-                devState = Device_Idle_SI;
-                intrPost();
-            } else {
-                devState = Device_Idle_S;
-            }
-        } else if (action == ACT_DATA_READY) {
-            // clear the BSY bit
-            status &= ~STATUS_BSY_BIT;
-            // set the DRQ bit
-            status |= STATUS_DRQ_BIT;
-
-            // copy the data into the data buffer
-            if (cmdReg.command == WDCC_IDENTIFY) {
-                // Reset the drqBytes for this block
-                drqBytesLeft = sizeof(struct ataparams);
-
-                memcpy((void *)dataBuffer, (void *)&driveID,
-                       sizeof(struct ataparams));
-            } else {
-                // Reset the drqBytes for this block
-                drqBytesLeft = SectorSize;
-
-                readDisk(curSector++, dataBuffer);
-            }
-
-            // put the first two bytes into the data register
-            memcpy((void *)&cmdReg.data, (void *)dataBuffer,
-                   sizeof(uint16_t));
-
-            if (!isIENSet()) {
-                devState = Data_Ready_INTRQ_In;
-                intrPost();
-            } else {
-                devState = Transfer_Data_In;
-            }
-        }
-        break;
-
-      case Data_Ready_INTRQ_In:
-        if (action == ACT_STAT_READ) {
-            devState = Transfer_Data_In;
-            intrClear();
-        }
-        break;
-
-      case Transfer_Data_In:
-        if (action == ACT_DATA_READ_BYTE || action == ACT_DATA_READ_SHORT) {
-            if (action == ACT_DATA_READ_BYTE) {
-                panic("DEBUG: READING DATA ONE BYTE AT A TIME!\n");
-            } else {
-                drqBytesLeft -= 2;
-                cmdBytesLeft -= 2;
-
-                // copy next short into data registers
-                if (drqBytesLeft)
-                    memcpy((void *)&cmdReg.data,
-                           (void *)&dataBuffer[SectorSize - drqBytesLeft],
-                           sizeof(uint16_t));
-            }
-
-            if (drqBytesLeft == 0) {
-                if (cmdBytesLeft == 0) {
-                    // Clear the BSY bit
-                    setComplete();
-                    devState = Device_Idle_S;
-                } else {
-                    devState = Prepare_Data_In;
-                    // set the BSY_BIT
-                    status |= STATUS_BSY_BIT;
-                    // clear the DRQ_BIT
-                    status &= ~STATUS_DRQ_BIT;
-
-                    /** @todo change this to a scheduled event to simulate
-                        disk delay */
-                    updateState(ACT_DATA_READY);
-                }
-            }
-        }
-        break;
-
-      case Prepare_Data_Out:
-        if (action == ACT_CMD_ERROR || cmdBytesLeft == 0) {
-            // clear the BSY bit
-            setComplete();
-
-            if (!isIENSet()) {
-                devState = Device_Idle_SI;
-                intrPost();
-            } else {
-                devState = Device_Idle_S;
-            }
-        } else if (action == ACT_DATA_READY && cmdBytesLeft != 0) {
-            // clear the BSY bit
-            status &= ~STATUS_BSY_BIT;
-            // set the DRQ bit
-            status |= STATUS_DRQ_BIT;
-
-            // clear the data buffer to get it ready for writes
-            memset(dataBuffer, 0, MAX_DMA_SIZE);
-
-            // reset the drqBytes for this block
-            drqBytesLeft = SectorSize;
-
-            if (cmdBytesLeft == cmdBytes || isIENSet()) {
-                devState = Transfer_Data_Out;
-            } else {
-                devState = Data_Ready_INTRQ_Out;
-                intrPost();
-            }
-        }
-        break;
-
-      case Data_Ready_INTRQ_Out:
-        if (action == ACT_STAT_READ) {
-            devState = Transfer_Data_Out;
-            intrClear();
-        }
-        break;
-
-      case Transfer_Data_Out:
-        if (action == ACT_DATA_WRITE_BYTE ||
-            action == ACT_DATA_WRITE_SHORT) {
-
-            if (action == ACT_DATA_READ_BYTE) {
-                panic("DEBUG: WRITING DATA ONE BYTE AT A TIME!\n");
-            } else {
-                // copy the latest short into the data buffer
-                memcpy((void *)&dataBuffer[SectorSize - drqBytesLeft],
-                       (void *)&cmdReg.data,
-                       sizeof(uint16_t));
-
-                drqBytesLeft -= 2;
-                cmdBytesLeft -= 2;
-            }
-
-            if (drqBytesLeft == 0) {
-                // copy the block to the disk
-                writeDisk(curSector++, dataBuffer);
-
-                // set the BSY bit
-                status |= STATUS_BSY_BIT;
-                // set the seek bit
-                status |= STATUS_SEEK_BIT;
-                // clear the DRQ bit
-                status &= ~STATUS_DRQ_BIT;
-
-                devState = Prepare_Data_Out;
-
-                /** @todo change this to a scheduled event to simulate
-                    disk delay */
-                updateState(ACT_DATA_READY);
-            }
-        }
-        break;
-
-      case Prepare_Data_Dma:
-        if (action == ACT_CMD_ERROR) {
-            // clear the BSY bit
-            setComplete();
-
-            if (!isIENSet()) {
-                devState = Device_Idle_SI;
-                intrPost();
-            } else {
-                devState = Device_Idle_S;
-            }
-        } else if (action == ACT_DMA_READY) {
-            // clear the BSY bit
-            status &= ~STATUS_BSY_BIT;
-            // set the DRQ bit
-            status |= STATUS_DRQ_BIT;
-
-            devState = Transfer_Data_Dma;
-
-            if (dmaState != Dma_Idle)
-                panic("Inconsistent DMA state, should be Dma_Idle\n");
-
-            dmaState = Dma_Start;
-            // wait for the write to the DMA start bit
-        }
-        break;
-
-      case Transfer_Data_Dma:
-        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
-            status |= STATUS_SEEK_BIT;
-            // clear the controller state for DMA transfer
-            ctrl->setDmaComplete(this);
-
-            if (!isIENSet()) {
-                devState = Device_Idle_SI;
-                intrPost();
-            } else {
-                devState = Device_Idle_S;
-            }
-        }
-        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);
-    }
-}
-
-void
-IdeDisk::serialize(CheckpointOut &cp) const
-{
-    // Check all outstanding events to see if they are scheduled
-    // these are all mutually exclusive
-    Tick reschedule = 0;
-    Events_t event = None;
-
-    int eventCount = 0;
-
-    if (dmaTransferEvent.scheduled()) {
-        reschedule = dmaTransferEvent.when();
-        event = Transfer;
-        eventCount++;
-    }
-    if (dmaReadWaitEvent.scheduled()) {
-        reschedule = dmaReadWaitEvent.when();
-        event = ReadWait;
-        eventCount++;
-    }
-    if (dmaWriteWaitEvent.scheduled()) {
-        reschedule = dmaWriteWaitEvent.when();
-        event = WriteWait;
-        eventCount++;
-    }
-    if (dmaPrdReadEvent.scheduled()) {
-        reschedule = dmaPrdReadEvent.when();
-        event = PrdRead;
-        eventCount++;
-    }
-    if (dmaReadEvent.scheduled()) {
-        reschedule = dmaReadEvent.when();
-        event = DmaRead;
-        eventCount++;
-    }
-    if (dmaWriteEvent.scheduled()) {
-        reschedule = dmaWriteEvent.when();
-        event = DmaWrite;
-        eventCount++;
-    }
-
-    assert(eventCount <= 1);
-
-    SERIALIZE_SCALAR(reschedule);
-    SERIALIZE_ENUM(event);
-
-    // Serialize device registers
-    SERIALIZE_SCALAR(cmdReg.data);
-    SERIALIZE_SCALAR(cmdReg.sec_count);
-    SERIALIZE_SCALAR(cmdReg.sec_num);
-    SERIALIZE_SCALAR(cmdReg.cyl_low);
-    SERIALIZE_SCALAR(cmdReg.cyl_high);
-    SERIALIZE_SCALAR(cmdReg.drive);
-    SERIALIZE_SCALAR(cmdReg.command);
-    SERIALIZE_SCALAR(status);
-    SERIALIZE_SCALAR(nIENBit);
-    SERIALIZE_SCALAR(devID);
-
-    // Serialize the PRD related information
-    SERIALIZE_SCALAR(curPrd.entry.baseAddr);
-    SERIALIZE_SCALAR(curPrd.entry.byteCount);
-    SERIALIZE_SCALAR(curPrd.entry.endOfTable);
-    SERIALIZE_SCALAR(curPrdAddr);
-
-    /** @todo need to serialized chunk generator stuff!! */
-    // Serialize current transfer related information
-    SERIALIZE_SCALAR(cmdBytesLeft);
-    SERIALIZE_SCALAR(cmdBytes);
-    SERIALIZE_SCALAR(drqBytesLeft);
-    SERIALIZE_SCALAR(curSector);
-    SERIALIZE_SCALAR(dmaRead);
-    SERIALIZE_SCALAR(intrPending);
-    SERIALIZE_SCALAR(dmaAborted);
-    SERIALIZE_ENUM(devState);
-    SERIALIZE_ENUM(dmaState);
-    SERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);
-}
-
-void
-IdeDisk::unserialize(CheckpointIn &cp)
-{
-    // Reschedule events that were outstanding
-    // these are all mutually exclusive
-    Tick reschedule = 0;
-    Events_t event = None;
-
-    UNSERIALIZE_SCALAR(reschedule);
-    UNSERIALIZE_ENUM(event);
-
-    switch (event) {
-      case None : 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
-    UNSERIALIZE_SCALAR(cmdReg.data);
-    UNSERIALIZE_SCALAR(cmdReg.sec_count);
-    UNSERIALIZE_SCALAR(cmdReg.sec_num);
-    UNSERIALIZE_SCALAR(cmdReg.cyl_low);
-    UNSERIALIZE_SCALAR(cmdReg.cyl_high);
-    UNSERIALIZE_SCALAR(cmdReg.drive);
-    UNSERIALIZE_SCALAR(cmdReg.command);
-    UNSERIALIZE_SCALAR(status);
-    UNSERIALIZE_SCALAR(nIENBit);
-    UNSERIALIZE_SCALAR(devID);
-
-    // Unserialize the PRD related information
-    UNSERIALIZE_SCALAR(curPrd.entry.baseAddr);
-    UNSERIALIZE_SCALAR(curPrd.entry.byteCount);
-    UNSERIALIZE_SCALAR(curPrd.entry.endOfTable);
-    UNSERIALIZE_SCALAR(curPrdAddr);
-
-    /** @todo need to serialized chunk generator stuff!! */
-    // Unserialize current transfer related information
-    UNSERIALIZE_SCALAR(cmdBytes);
-    UNSERIALIZE_SCALAR(cmdBytesLeft);
-    UNSERIALIZE_SCALAR(drqBytesLeft);
-    UNSERIALIZE_SCALAR(curSector);
-    UNSERIALIZE_SCALAR(dmaRead);
-    UNSERIALIZE_SCALAR(intrPending);
-    UNSERIALIZE_SCALAR(dmaAborted);
-    UNSERIALIZE_ENUM(devState);
-    UNSERIALIZE_ENUM(dmaState);
-    UNSERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);
-}
-
-IdeDisk *
-IdeDiskParams::create()
-{
-    return new IdeDisk(this);
-}
diff --git a/src/dev/ide_disk.hh b/src/dev/ide_disk.hh
deleted file mode 100644 (file)
index 45b0dd1..0000000
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * 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.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Andrew Schultz
- */
-
-/** @file
- * Device model for an IDE disk
- */
-
-#ifndef __IDE_DISK_HH__
-#define __IDE_DISK_HH__
-
-#include "base/statistics.hh"
-#include "dev/disk_image.hh"
-#include "dev/ide_atareg.h"
-#include "dev/ide_ctrl.hh"
-#include "dev/ide_wdcreg.h"
-#include "dev/io_device.hh"
-#include "params/IdeDisk.hh"
-#include "sim/eventq.hh"
-
-class ChunkGenerator;
-
-#define DMA_BACKOFF_PERIOD      200
-
-#define MAX_DMA_SIZE            0x20000  // 128K
-#define MAX_SINGLE_DMA_SIZE     0x10000
-#define MAX_MULTSECT            (128)
-
-#define PRD_BASE_MASK  0xfffffffe
-#define PRD_COUNT_MASK 0xfffe
-#define PRD_EOT_MASK   0x8000
-
-typedef struct PrdEntry {
-    uint32_t baseAddr;
-    uint16_t byteCount;
-    uint16_t endOfTable;
-} PrdEntry_t;
-
-class PrdTableEntry {
-  public:
-    PrdEntry_t entry;
-
-    uint32_t getBaseAddr()
-    {
-        return (entry.baseAddr & PRD_BASE_MASK);
-    }
-
-    uint32_t getByteCount()
-    {
-        return ((entry.byteCount == 0) ? MAX_SINGLE_DMA_SIZE :
-                (entry.byteCount & PRD_COUNT_MASK));
-    }
-
-    uint16_t getEOT()
-    {
-        return (entry.endOfTable & PRD_EOT_MASK);
-    }
-};
-
-#define DATA_OFFSET     (0)
-#define ERROR_OFFSET    (1)
-#define FEATURES_OFFSET (1)
-#define NSECTOR_OFFSET  (2)
-#define SECTOR_OFFSET   (3)
-#define LCYL_OFFSET     (4)
-#define HCYL_OFFSET     (5)
-#define SELECT_OFFSET   (6)
-#define DRIVE_OFFSET    (6)
-#define STATUS_OFFSET   (7)
-#define COMMAND_OFFSET  (7)
-
-#define CONTROL_OFFSET  (2)
-#define ALTSTAT_OFFSET  (2)
-
-#define SELECT_DEV_BIT  0x10
-#define CONTROL_RST_BIT 0x04
-#define CONTROL_IEN_BIT 0x02
-#define STATUS_BSY_BIT  0x80
-#define STATUS_DRDY_BIT 0x40
-#define STATUS_DRQ_BIT  0x08
-#define STATUS_SEEK_BIT 0x10
-#define STATUS_DF_BIT   0x20
-#define DRIVE_LBA_BIT   0x40
-
-#define DEV0 (0)
-#define DEV1 (1)
-
-typedef struct CommandReg {
-    uint16_t data;
-    uint8_t error;
-    uint8_t sec_count;
-    uint8_t sec_num;
-    uint8_t cyl_low;
-    uint8_t cyl_high;
-    union {
-        uint8_t drive;
-        uint8_t head;
-    };
-    uint8_t command;
-} CommandReg_t;
-
-typedef enum Events {
-    None = 0,
-    Transfer,
-    ReadWait,
-    WriteWait,
-    PrdRead,
-    DmaRead,
-    DmaWrite
-} Events_t;
-
-typedef enum DevAction {
-    ACT_NONE = 0,
-    ACT_CMD_WRITE,
-    ACT_CMD_COMPLETE,
-    ACT_CMD_ERROR,
-    ACT_SELECT_WRITE,
-    ACT_STAT_READ,
-    ACT_DATA_READY,
-    ACT_DATA_READ_BYTE,
-    ACT_DATA_READ_SHORT,
-    ACT_DATA_WRITE_BYTE,
-    ACT_DATA_WRITE_SHORT,
-    ACT_DMA_READY,
-    ACT_DMA_DONE,
-    ACT_SRST_SET,
-    ACT_SRST_CLEAR
-} DevAction_t;
-
-typedef enum DevState {
-    // Device idle
-    Device_Idle_S = 0,
-    Device_Idle_SI,
-    Device_Idle_NS,
-
-    // Software reset
-    Device_Srst,
-
-    // Non-data commands
-    Command_Execution,
-
-    // PIO data-in (data to host)
-    Prepare_Data_In,
-    Data_Ready_INTRQ_In,
-    Transfer_Data_In,
-
-    // PIO data-out (data from host)
-    Prepare_Data_Out,
-    Data_Ready_INTRQ_Out,
-    Transfer_Data_Out,
-
-    // DMA protocol
-    Prepare_Data_Dma,
-    Transfer_Data_Dma,
-    Device_Dma_Abort
-} DevState_t;
-
-typedef enum DmaState {
-    Dma_Idle = 0,
-    Dma_Start,
-    Dma_Transfer
-} DmaState_t;
-
-class IdeController;
-
-/**
- * IDE Disk device model
- */
-class IdeDisk : public SimObject
-{
-  protected:
-    /** The IDE controller for this disk. */
-    IdeController *ctrl;
-    /** The image that contains the data of this disk. */
-    DiskImage *image;
-
-  protected:
-    /** The disk delay in microseconds. */
-    int diskDelay;
-
-  private:
-    /** Drive identification structure for this disk */
-    struct ataparams driveID;
-    /** Data buffer for transfers */
-    uint8_t *dataBuffer;
-    /** Number of bytes in command data transfer */
-    uint32_t cmdBytes;
-    /** Number of bytes left in command data transfer */
-    uint32_t cmdBytesLeft;
-    /** Number of bytes left in DRQ block */
-    uint32_t drqBytesLeft;
-    /** Current sector in access */
-    uint32_t curSector;
-    /** Command block registers */
-    CommandReg_t cmdReg;
-    /** Status register */
-    uint8_t status;
-    /** Interrupt enable bit */
-    bool nIENBit;
-    /** Device state */
-    DevState_t devState;
-    /** Dma state */
-    DmaState_t dmaState;
-    /** Dma transaction is a read */
-    bool dmaRead;
-    /** PRD table base address */
-    uint32_t curPrdAddr;
-    /** PRD entry */
-    PrdTableEntry curPrd;
-    /** Device ID (master=0/slave=1) */
-    int devID;
-    /** Interrupt pending */
-    bool intrPending;
-    /** DMA Aborted */
-    bool dmaAborted;
-
-    Stats::Scalar dmaReadFullPages;
-    Stats::Scalar dmaReadBytes;
-    Stats::Scalar dmaReadTxs;
-    Stats::Scalar dmaWriteFullPages;
-    Stats::Scalar dmaWriteBytes;
-    Stats::Scalar dmaWriteTxs;
-
-  public:
-    typedef IdeDiskParams Params;
-    IdeDisk(const Params *p);
-
-    /**
-     * Delete the data buffer.
-     */
-    ~IdeDisk();
-
-    /**
-     * Reset the device state
-     */
-    void reset(int id);
-
-    /**
-     * Register Statistics
-     */
-    void regStats() override;
-
-    /**
-     * Set the controller for this device
-     * @param c The IDE controller
-     */
-    void setController(IdeController *c) {
-        if (ctrl) panic("Cannot change the controller once set!\n");
-        ctrl = c;
-    }
-
-    // Device register read/write
-    void readCommand(const Addr offset, int size, uint8_t *data);
-    void readControl(const Addr offset, int size, uint8_t *data);
-    void writeCommand(const Addr offset, int size, const uint8_t *data);
-    void writeControl(const Addr offset, int size, const uint8_t *data);
-
-    // Start/abort functions
-    void startDma(const uint32_t &prdTableBase);
-    void abortDma();
-
-  private:
-    void startCommand();
-
-    // Interrupt management
-    void intrPost();
-    void intrClear();
-
-    // DMA stuff
-    void doDmaTransfer();
-    friend class EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer>;
-    EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer> dmaTransferEvent;
-
-    void doDmaDataRead();
-
-    void doDmaRead();
-    ChunkGenerator *dmaReadCG;
-    friend class EventWrapper<IdeDisk, &IdeDisk::doDmaRead>;
-    EventWrapper<IdeDisk, &IdeDisk::doDmaRead> dmaReadWaitEvent;
-
-    void doDmaDataWrite();
-
-    void doDmaWrite();
-    ChunkGenerator *dmaWriteCG;
-    friend class EventWrapper<IdeDisk, &IdeDisk::doDmaWrite>;
-    EventWrapper<IdeDisk, &IdeDisk::doDmaWrite> dmaWriteWaitEvent;
-
-    void dmaPrdReadDone();
-    friend class EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone>;
-    EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone> dmaPrdReadEvent;
-
-    void dmaReadDone();
-    friend class EventWrapper<IdeDisk, &IdeDisk::dmaReadDone>;
-    EventWrapper<IdeDisk, &IdeDisk::dmaReadDone> dmaReadEvent;
-
-    void dmaWriteDone();
-    friend class EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone>;
-    EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone> dmaWriteEvent;
-
-    // Disk image read/write
-    void readDisk(uint32_t sector, uint8_t *data);
-    void writeDisk(uint32_t sector, uint8_t *data);
-
-    // State machine management
-    void updateState(DevAction_t action);
-
-    // Utility functions
-    bool isBSYSet() { return (status & STATUS_BSY_BIT); }
-    bool isIENSet() { return nIENBit; }
-    bool isDEVSelect();
-
-    void setComplete()
-    {
-        // clear out the status byte
-        status = 0;
-        // set the DRDY bit
-        status |= STATUS_DRDY_BIT;
-        // set the SEEK bit
-        status |= STATUS_SEEK_BIT;
-    }
-
-    uint32_t getLBABase()
-    {
-        return  (Addr)(((cmdReg.head & 0xf) << 24) | (cmdReg.cyl_high << 16) |
-                       (cmdReg.cyl_low << 8) | (cmdReg.sec_num));
-    }
-
-    inline Addr pciToDma(Addr pciAddr);
-
-    void serialize(CheckpointOut &cp) const override;
-    void unserialize(CheckpointIn &cp) override;
-};
-
-
-#endif // __IDE_DISK_HH__
diff --git a/src/dev/ide_wdcreg.h b/src/dev/ide_wdcreg.h
deleted file mode 100644 (file)
index f6a59c9..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/*      $OpenBSD: wdcreg.h,v 1.13 2004/09/24 07:05:44 grange Exp $     */
-/*     $NetBSD: wdcreg.h,v 1.22 1999/03/07 14:02:54 bouyer Exp $       */
-
-/*-
- * Copyright (c) 1991 The Regents of the University of California
- * All rights reserved
- *
- * This code is derived from software contributed to Berkeley by
- * William Jolitz.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     @(#)wdreg.h     7.1 (Berkeley) 5/9/91
- */
-
-#ifndef _DEV_IC_WDCREG_H_
-#define _DEV_IC_WDCREG_H_
-
-/*
- * Controller register (wdr_ctlr)
- */
-#define WDCTL_4BIT     0x08    /* use four head bits (wd1003) */
-#define WDCTL_RST      0x04    /* reset the controller */
-#define WDCTL_IDS      0x02    /* disable controller interrupts */
-
-/*
- * Status bits.
- */
-#define WDCS_BSY       0x80    /* busy */
-#define WDCS_DRDY      0x40    /* drive ready */
-#define WDCS_DWF       0x20    /* drive write fault */
-#define WDCS_DSC       0x10    /* drive seek complete */
-#define WDCS_DRQ       0x08    /* data request */
-#define WDCS_CORR      0x04    /* corrected data */
-#define WDCS_IDX       0x02    /* index */
-#define WDCS_ERR       0x01    /* error */
-#define WDCS_BITS      "\020\010BSY\007DRDY\006DWF\005DSC\004DRQ\003CORR\002IDX\001ERR"
-
-/*
- * Error bits.
- */
-#define WDCE_BBK       0x80    /* bad block detected */
-#define WDCE_CRC       0x80    /* CRC error (Ultra-DMA only) */
-#define WDCE_UNC       0x40    /* uncorrectable data error */
-#define WDCE_MC                0x20    /* media changed */
-#define WDCE_IDNF      0x10    /* id not found */
-#define WDCE_MCR       0x08    /* media change requested */
-#define WDCE_ABRT      0x04    /* aborted command */
-#define WDCE_TK0NF     0x02    /* track 0 not found */
-#define WDCE_AMNF      0x01    /* address mark not found */
-
-/*
- * Commands for Disk Controller.
- */
-#define WDCC_NOP       0x00    /* NOP - Always fail with "aborted command" */
-#define WDCC_RECAL     0x10    /* disk restore code -- resets cntlr */
-
-#define WDCC_READ      0x20    /* disk read code */
-#define WDCC_WRITE     0x30    /* disk write code */
-#define WDCC__LONG     0x02    /* modifier -- access ecc bytes */
-#define WDCC__NORETRY  0x01    /* modifier -- no retrys */
-
-#define WDCC_FORMAT    0x50    /* disk format code */
-#define WDCC_DIAGNOSE  0x90    /* controller diagnostic */
-#define WDCC_IDP       0x91    /* initialize drive parameters */
-
-#define WDCC_READMULTI 0xc4    /* read multiple */
-#define WDCC_WRITEMULTI        0xc5    /* write multiple */
-#define WDCC_SETMULTI  0xc6    /* set multiple mode */
-
-#define WDCC_READDMA   0xc8    /* read with DMA */
-#define WDCC_WRITEDMA  0xca    /* write with DMA */
-
-#define WDCC_ACKMC     0xdb    /* acknowledge media change */
-#define WDCC_LOCK      0xde    /* lock drawer */
-#define WDCC_UNLOCK    0xdf    /* unlock drawer */
-
-#define WDCC_FLUSHCACHE        0xe7    /* Flush cache */
-#define WDCC_IDENTIFY  0xec    /* read parameters from controller */
-#define SET_FEATURES   0xef    /* set features */
-
-#define WDCC_IDLE      0xe3    /* set idle timer & enter idle mode */
-#define WDCC_IDLE_IMMED        0xe1    /* enter idle mode */
-#define WDCC_SLEEP     0xe6    /* enter sleep mode */
-#define WDCC_STANDBY   0xe2    /* set standby timer & enter standby mode */
-#define WDCC_STANDBY_IMMED 0xe0        /* enter standby mode */
-#define WDCC_CHECK_PWR 0xe5    /* check power mode */
-
-#define WDCC_READ_EXT          0x24 /* read 48-bit addressing */
-#define WDCC_WRITE_EXT         0x34 /* write 48-bit addressing */
-
-#define WDCC_READMULTI_EXT     0x29 /* read multiple 48-bit addressing */
-#define WDCC_WRITEMULTI_EXT    0x39 /* write multiple 48-bit addressing */
-
-#define WDCC_READDMA_EXT       0x25 /* read 48-bit addressing with DMA */
-#define WDCC_WRITEDMA_EXT      0x35 /* write 48-bit addressing with DMA */
-
-#define WDCC_FLUSHCACHE_EXT    0xea /* 48-bit addressing flush cache */
-
-/* Subcommands for SET_FEATURES (features register ) */
-#define WDSF_8BIT_PIO_EN       0x01 /* Enable 8bit PIO (CFA featureset) */
-#define WDSF_EN_WR_CACHE       0x02
-#define WDSF_SET_MODE          0x03
-#define WDSF_REASSIGN_EN       0x04 /* Obsolete in ATA-6 */
-#define WDSF_APM_EN            0x05 /* Enable Adv. Power Management */
-#define WDSF_PUIS_EN           0x06 /* Enable Power-Up In Standby */
-#define WDSF_PUIS_SPINUP       0x07 /* Power-Up In Standby spin-up */
-#define WDSF_CFA_MODE1_EN      0x0A /* Enable CFA power mode 1 */
-#define WDSF_RMSN_DS           0x31 /* Disable Removable Media Status */
-#define WDSF_RETRY_DS          0x33 /* Obsolete in ATA-6 */
-#define WDSF_AAM_EN            0x42 /* Enable Autom. Acoustic Management */
-#define WDSF_SET_CACHE_SGMT    0x54 /* Obsolete in ATA-6 */
-#define WDSF_READAHEAD_DS      0x55 /* Disable read look-ahead */
-#define WDSF_RLSE_EN           0x5D /* Enable release interrupt */
-#define WDSF_SRV_EN            0x5E /* Enable SERVICE interrupt */
-#define WDSF_POD_DS            0x66
-#define WDSF_ECC_DS            0x77
-#define WDSF_8BIT_PIO_DS       0x81 /* Disable 8bit PIO (CFA featureset) */
-#define WDSF_WRITE_CACHE_DS    0x82
-#define WDSF_REASSIGN_DS       0x84
-#define WDSF_APM_DS            0x85 /* Disable Adv. Power Management */
-#define WDSF_PUIS_DS           0x86 /* Disable Power-Up In Standby */
-#define WDSF_ECC_EN            0x88
-#define WDSF_CFA_MODE1_DS      0x8A /* Disable CFA power mode 1 */
-#define WDSF_RMSN_EN           0x95 /* Enable Removable Media Status */
-#define WDSF_RETRY_EN          0x99 /* Obsolete in ATA-6 */
-#define WDSF_SET_CURRENT       0x9A /* Obsolete in ATA-6 */
-#define WDSF_READAHEAD_EN      0xAA
-#define WDSF_PREFETCH_SET      0xAB /* Obsolete in ATA-6 */
-#define WDSF_AAM_DS            0xC2 /* Disable Autom. Acoustic Management */
-#define WDSF_POD_EN            0xCC
-#define WDSF_RLSE_DS           0xDD /* Disable release interrupt */
-#define WDSF_SRV_DS            0xDE /* Disable SERVICE interrupt */
-#define WDSF_READ_NATIVE_MAX    0xF8
-#define WDSF_SEEK               0x70
-#define WDSF_VERIFY             0x40
-
-/* parameters uploaded to device/heads register */
-#define WDSD_IBM       0xa0    /* forced to 512 byte sector, ecc */
-#define WDSD_CHS       0x00    /* cylinder/head/sector addressing */
-#define WDSD_LBA       0x40    /* logical block addressing */
-
-/* Commands for ATAPI devices */
-#define ATAPI_CHECK_POWER_MODE 0xe5
-#define ATAPI_EXEC_DRIVE_DIAGS 0x90
-#define ATAPI_IDLE_IMMEDIATE   0xe1
-#define ATAPI_NOP              0x00
-#define ATAPI_PKT_CMD          0xa0
-#define ATAPI_IDENTIFY_DEVICE  0xa1
-#define ATAPI_SOFT_RESET       0x08
-#define ATAPI_DEVICE_RESET     0x08 /* ATA/ATAPI-5 name for soft reset */
-#define ATAPI_SLEEP            0xe6
-#define ATAPI_STANDBY_IMMEDIATE        0xe0
-#define ATAPI_SMART            0xB0 /* SMART operations */
-#define ATAPI_SETMAX           0xF9 /* Set Max Address */
-#define ATAPI_WRITEEXT         0x34 /* Write sectors Ext */
-#define ATAPI_SETMAXEXT                0x37 /* Set Max Address Ext */
-#define ATAPI_WRITEMULTIEXT    0x39 /* Write Multi Ext */
-
-/* Bytes used by ATAPI_PACKET_COMMAND ( feature register) */
-#define ATAPI_PKT_CMD_FTRE_DMA 0x01
-#define ATAPI_PKT_CMD_FTRE_OVL 0x02
-
-/* ireason */
-#define WDCI_CMD       0x01 /* command(1) or data(0) */
-#define WDCI_IN                0x02 /* transfer to(1) or from(0) the host */
-#define WDCI_RELEASE   0x04 /* bus released until completion */
-
-#define PHASE_CMDOUT   (WDCS_DRQ | WDCI_CMD)
-#define PHASE_DATAIN   (WDCS_DRQ | WDCI_IN)
-#define PHASE_DATAOUT  WDCS_DRQ
-#define PHASE_COMPLETED        (WDCI_IN | WDCI_CMD)
-#define PHASE_ABORTED  0
-
-#endif /* !_DEV_IC_WDCREG_H_ */
diff --git a/src/dev/simple_disk.cc b/src/dev/simple_disk.cc
deleted file mode 100644 (file)
index 26e8239..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Nathan Binkert
- */
-
-/* @file
- * Simple disk interface for the system console
- */
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <cstring>
-#include <string>
-
-#include "base/misc.hh"
-#include "base/trace.hh"
-#include "debug/SimpleDisk.hh"
-#include "debug/SimpleDiskData.hh"
-#include "dev/disk_image.hh"
-#include "dev/simple_disk.hh"
-#include "mem/port_proxy.hh"
-#include "sim/system.hh"
-
-using namespace std;
-
-SimpleDisk::SimpleDisk(const Params *p)
-    : SimObject(p), system(p->system), image(p->disk)
-{}
-
-SimpleDisk::~SimpleDisk()
-{}
-
-
-void
-SimpleDisk::read(Addr addr, baddr_t block, int count) const
-{
-    uint8_t *data = new uint8_t[SectorSize * count];
-
-    if (count & (SectorSize - 1))
-        panic("Not reading a multiple of a sector (count = %d)", count);
-
-    for (int i = 0, j = 0; i < count; i += SectorSize, j++)
-        image->read(data + i, block + j);
-
-    system->physProxy.writeBlob(addr, data, count);
-
-    DPRINTF(SimpleDisk, "read  block=%#x len=%d\n", (uint64_t)block, count);
-    DDUMP(SimpleDiskData, data, count);
-
-    delete [] data;
-}
-
-void
-SimpleDisk::write(Addr addr, baddr_t block, int count)
-{
-    panic("unimplemented!\n");
-
-#if 0
-    uint8_t *data = physmem->dma_addr(addr, count);
-    if (!data)
-        panic("dma out of range! write addr=%#x count=%d\n", addr, count);
-
-    image->write(data, block, count);
-#endif
-}
-
-SimpleDisk *
-SimpleDiskParams::create()
-{
-    return new SimpleDisk(this);
-}
diff --git a/src/dev/simple_disk.hh b/src/dev/simple_disk.hh
deleted file mode 100644 (file)
index 1a95bd5..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Nathan Binkert
- */
-
-/* @file
- * Simple disk interface for the system console
- */
-
-#ifndef __DEV_SIMPLE_DISK_HH__
-#define __DEV_SIMPLE_DISK_HH__
-
-#include "params/SimpleDisk.hh"
-#include "sim/sim_object.hh"
-
-class DiskImage;
-class System;
-
-/*
- * Trivial interface to a disk image used by the System Console
- */
-class SimpleDisk : public SimObject
-{
-  public:
-    typedef uint64_t baddr_t;
-
-  protected:
-    System  *system;
-    DiskImage *image;
-
-  public:
-    typedef SimpleDiskParams Params;
-    SimpleDisk(const Params *p);
-    ~SimpleDisk();
-
-    void read(Addr addr, baddr_t block, int count) const;
-    void write(Addr addr, baddr_t block, int count);
-};
-
-#endif // __DEV_SIMPLE_DISK_HH__
index 4772e86549db2c87adacff45ef4df0373857a28a..1de625eba8bf0627beea794ce3a969f6fb69c458 100644 (file)
@@ -36,7 +36,6 @@
 #ifndef __DEV_SPARC_IOB_HH__
 #define __DEV_SPARC_IOB_HH__
 
-#include "dev/disk_image.hh"
 #include "dev/io_device.hh"
 #include "params/Iob.hh"
 
index 6242ed9436ed27bbd67e167985bf5a4de8e285e1..2d551fe3fe4a40a26fb44e7d793779529077c462 100644 (file)
@@ -36,8 +36,8 @@
 #ifndef __DEV_SPARC_MM_DISK_HH__
 #define __DEV_SPARC_MM_DISK_HH__
 
-#include "dev/disk_image.hh"
 #include "dev/io_device.hh"
+#include "dev/storage/disk_image.hh"
 #include "params/MmDisk.hh"
 
 class MmDisk : public BasicPioDevice
diff --git a/src/dev/storage/DiskImage.py b/src/dev/storage/DiskImage.py
new file mode 100644 (file)
index 0000000..5a3bc54
--- /dev/null
@@ -0,0 +1,48 @@
+# Copyright (c) 2005-2007 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
+from m5.SimObject import SimObject
+from m5.params import *
+class DiskImage(SimObject):
+    type = 'DiskImage'
+    abstract = True
+    cxx_header = "dev/storage/disk_image.hh"
+    image_file = Param.String("disk image file")
+    read_only = Param.Bool(False, "read only image")
+
+class RawDiskImage(DiskImage):
+    type = 'RawDiskImage'
+    cxx_header = "dev/storage/disk_image.hh"
+
+class CowDiskImage(DiskImage):
+    type = 'CowDiskImage'
+    cxx_header = "dev/storage/disk_image.hh"
+    child = Param.DiskImage(RawDiskImage(read_only=True),
+                            "child image")
+    table_size = Param.Int(65536, "initial table size")
+    image_file = ""
diff --git a/src/dev/storage/Ide.py b/src/dev/storage/Ide.py
new file mode 100644 (file)
index 0000000..fc3f356
--- /dev/null
@@ -0,0 +1,70 @@
+# Copyright (c) 2005-2007 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
+from m5.SimObject import SimObject
+from m5.params import *
+from PciDevice import PciDevice
+
+class IdeID(Enum): vals = ['master', 'slave']
+
+class IdeDisk(SimObject):
+    type = 'IdeDisk'
+    cxx_header = "dev/storage/ide_disk.hh"
+    delay = Param.Latency('1us', "Fixed disk delay in microseconds")
+    driveID = Param.IdeID('master', "Drive ID")
+    image = Param.DiskImage("Disk image")
+
+class IdeController(PciDevice):
+    type = 'IdeController'
+    cxx_header = "dev/storage/ide_ctrl.hh"
+    disks = VectorParam.IdeDisk("IDE disks attached to this controller")
+
+    VendorID = 0x8086
+    DeviceID = 0x7111
+    Command = 0x0
+    Status = 0x280
+    Revision = 0x0
+    ClassCode = 0x01
+    SubClassCode = 0x01
+    ProgIF = 0x85
+    BAR0 = 0x00000001
+    BAR1 = 0x00000001
+    BAR2 = 0x00000001
+    BAR3 = 0x00000001
+    BAR4 = 0x00000001
+    BAR5 = 0x00000001
+    InterruptLine = 0x1f
+    InterruptPin = 0x01
+    BAR0Size = '8B'
+    BAR1Size = '4B'
+    BAR2Size = '8B'
+    BAR3Size = '4B'
+    BAR4Size = '16B'
+
+    io_shift = Param.UInt32(0x0, "IO port shift");
+    ctrl_offset = Param.UInt32(0x0, "IDE disk control offset")
diff --git a/src/dev/storage/SConscript b/src/dev/storage/SConscript
new file mode 100644 (file)
index 0000000..b5ddece
--- /dev/null
@@ -0,0 +1,73 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2015 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) 2006 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Steve Reinhardt
+#          Gabe Black
+#          Andreas Sandberg
+
+Import('*')
+
+if env['TARGET_ISA'] == 'null':
+    Return()
+
+# Controllers
+SimObject('Ide.py')
+
+Source('ide_ctrl.cc')
+Source('ide_disk.cc')
+
+DebugFlag('IdeCtrl')
+DebugFlag('IdeDisk')
+
+# Disk models
+SimObject('DiskImage.py')
+SimObject('SimpleDisk.py')
+
+Source('disk_image.cc')
+Source('simple_disk.cc')
+
+DebugFlag('DiskImageRead')
+DebugFlag('DiskImageWrite')
+DebugFlag('SimpleDisk')
+DebugFlag('SimpleDiskData')
+
+
+CompoundFlag('DiskImageAll', [ 'DiskImageRead', 'DiskImageWrite' ])
+CompoundFlag('IdeAll', [ 'IdeCtrl', 'IdeDisk' ])
diff --git a/src/dev/storage/SimpleDisk.py b/src/dev/storage/SimpleDisk.py
new file mode 100644 (file)
index 0000000..01b41ee
--- /dev/null
@@ -0,0 +1,37 @@
+# Copyright (c) 2005-2007 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
+from m5.SimObject import SimObject
+from m5.params import *
+from m5.proxy import *
+
+class SimpleDisk(SimObject):
+    type = 'SimpleDisk'
+    cxx_header = "dev/storage/simple_disk.hh"
+    disk = Param.DiskImage("Disk Image")
+    system = Param.System(Parent.any, "System Pointer")
diff --git a/src/dev/storage/disk_image.cc b/src/dev/storage/disk_image.cc
new file mode 100644 (file)
index 0000000..24688f5
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+/** @file
+ * Disk Image Definitions
+ */
+
+#include "dev/storage/disk_image.hh"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#include <cerrno>
+#include <cstring>
+#include <fstream>
+#include <string>
+
+#include "base/callback.hh"
+#include "base/misc.hh"
+#include "base/trace.hh"
+#include "debug/DiskImageRead.hh"
+#include "debug/DiskImageWrite.hh"
+#include "sim/byteswap.hh"
+#include "sim/sim_exit.hh"
+
+using namespace std;
+
+////////////////////////////////////////////////////////////////////////
+//
+// Raw Disk image
+//
+RawDiskImage::RawDiskImage(const Params* p)
+    : DiskImage(p), disk_size(0)
+{ open(p->image_file, p->read_only); }
+
+RawDiskImage::~RawDiskImage()
+{ close(); }
+
+void
+RawDiskImage::open(const string &filename, bool rd_only)
+{
+    if (!filename.empty()) {
+        initialized = true;
+        readonly = rd_only;
+        file = filename;
+
+        ios::openmode mode = ios::in | ios::binary;
+        if (!readonly)
+            mode |= ios::out;
+        stream.open(file.c_str(), mode);
+        if (!stream.is_open())
+            panic("Error opening %s", filename);
+    }
+}
+
+void
+RawDiskImage::close()
+{
+    stream.close();
+}
+
+std::streampos
+RawDiskImage::size() const
+{
+    if (disk_size == 0) {
+        if (!stream.is_open())
+            panic("file not open!\n");
+        stream.seekg(0, ios::end);
+        disk_size = stream.tellg();
+    }
+
+    return disk_size / SectorSize;
+}
+
+std::streampos
+RawDiskImage::read(uint8_t *data, std::streampos offset) const
+{
+    if (!initialized)
+        panic("RawDiskImage not initialized");
+
+    if (!stream.is_open())
+        panic("file not open!\n");
+
+    stream.seekg(offset * SectorSize, ios::beg);
+    if (!stream.good())
+        panic("Could not seek to location in file");
+
+    streampos pos = stream.tellg();
+    stream.read((char *)data, SectorSize);
+
+    DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
+    DDUMP(DiskImageRead, data, SectorSize);
+
+    return stream.tellg() - pos;
+}
+
+std::streampos
+RawDiskImage::write(const uint8_t *data, std::streampos offset)
+{
+    if (!initialized)
+        panic("RawDiskImage not initialized");
+
+    if (readonly)
+        panic("Cannot write to a read only disk image");
+
+    if (!stream.is_open())
+        panic("file not open!\n");
+
+    stream.seekp(offset * SectorSize, ios::beg);
+    if (!stream.good())
+        panic("Could not seek to location in file");
+
+    DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
+    DDUMP(DiskImageWrite, data, SectorSize);
+
+    streampos pos = stream.tellp();
+    stream.write((const char *)data, SectorSize);
+    return stream.tellp() - pos;
+}
+
+RawDiskImage *
+RawDiskImageParams::create()
+{
+    return new RawDiskImage(this);
+}
+
+////////////////////////////////////////////////////////////////////////
+//
+// Copy on Write Disk image
+//
+const uint32_t CowDiskImage::VersionMajor = 1;
+const uint32_t CowDiskImage::VersionMinor = 0;
+
+class CowDiskCallback : public Callback
+{
+  private:
+    CowDiskImage *image;
+
+  public:
+    CowDiskCallback(CowDiskImage *i) : image(i) {}
+    void process() { image->save(); delete this; }
+};
+
+CowDiskImage::CowDiskImage(const Params *p)
+    : DiskImage(p), filename(p->image_file), child(p->child), table(NULL)
+{
+    if (filename.empty()) {
+        initSectorTable(p->table_size);
+    } else {
+        if (!open(filename)) {
+            if (p->read_only)
+                fatal("could not open read-only file");
+            initSectorTable(p->table_size);
+        }
+
+        if (!p->read_only)
+            registerExitCallback(new CowDiskCallback(this));
+    }
+}
+
+CowDiskImage::~CowDiskImage()
+{
+    SectorTable::iterator i = table->begin();
+    SectorTable::iterator end = table->end();
+
+    while (i != end) {
+        delete (*i).second;
+        ++i;
+    }
+}
+
+void
+SafeRead(ifstream &stream, void *data, int count)
+{
+    stream.read((char *)data, count);
+    if (!stream.is_open())
+        panic("file not open");
+
+    if (stream.eof())
+        panic("premature end-of-file");
+
+    if (stream.bad() || stream.fail())
+        panic("error reading cowdisk image");
+}
+
+template<class T>
+void
+SafeRead(ifstream &stream, T &data)
+{
+    SafeRead(stream, &data, sizeof(data));
+}
+
+template<class T>
+void
+SafeReadSwap(ifstream &stream, T &data)
+{
+    SafeRead(stream, &data, sizeof(data));
+    data = letoh(data); //is this the proper byte order conversion?
+}
+
+bool
+CowDiskImage::open(const string &file)
+{
+    ifstream stream(file.c_str());
+    if (!stream.is_open())
+        return false;
+
+    if (stream.fail() || stream.bad())
+        panic("Error opening %s", file);
+
+    uint64_t magic;
+    SafeRead(stream, magic);
+
+    if (memcmp(&magic, "COWDISK!", sizeof(magic)) != 0)
+        panic("Could not open %s: Invalid magic", file);
+
+    uint32_t major, minor;
+    SafeReadSwap(stream, major);
+    SafeReadSwap(stream, minor);
+
+    if (major != VersionMajor && minor != VersionMinor)
+        panic("Could not open %s: invalid version %d.%d != %d.%d",
+              file, major, minor, VersionMajor, VersionMinor);
+
+    uint64_t sector_count;
+    SafeReadSwap(stream, sector_count);
+    table = new SectorTable(sector_count);
+
+
+    for (uint64_t i = 0; i < sector_count; i++) {
+        uint64_t offset;
+        SafeReadSwap(stream, offset);
+
+        Sector *sector = new Sector;
+        SafeRead(stream, sector, sizeof(Sector));
+
+        assert(table->find(offset) == table->end());
+        (*table)[offset] = sector;
+    }
+
+    stream.close();
+
+    initialized = true;
+    return true;
+}
+
+void
+CowDiskImage::initSectorTable(int hash_size)
+{
+    table = new SectorTable(hash_size);
+
+    initialized = true;
+}
+
+void
+SafeWrite(ofstream &stream, const void *data, int count)
+{
+    stream.write((const char *)data, count);
+    if (!stream.is_open())
+        panic("file not open");
+
+    if (stream.eof())
+        panic("premature end-of-file");
+
+    if (stream.bad() || stream.fail())
+        panic("error reading cowdisk image");
+}
+
+template<class T>
+void
+SafeWrite(ofstream &stream, const T &data)
+{
+    SafeWrite(stream, &data, sizeof(data));
+}
+
+template<class T>
+void
+SafeWriteSwap(ofstream &stream, const T &data)
+{
+    T swappeddata = letoh(data); //is this the proper byte order conversion?
+    SafeWrite(stream, &swappeddata, sizeof(data));
+}
+void
+CowDiskImage::save() const
+{
+    save(filename);
+}
+
+void
+CowDiskImage::save(const string &file) const
+{
+    if (!initialized)
+        panic("RawDiskImage not initialized");
+
+    ofstream stream(file.c_str());
+    if (!stream.is_open() || stream.fail() || stream.bad())
+        panic("Error opening %s", file);
+
+    uint64_t magic;
+    memcpy(&magic, "COWDISK!", sizeof(magic));
+    SafeWrite(stream, magic);
+
+    SafeWriteSwap(stream, (uint32_t)VersionMajor);
+    SafeWriteSwap(stream, (uint32_t)VersionMinor);
+    SafeWriteSwap(stream, (uint64_t)table->size());
+
+    uint64_t size = table->size();
+    SectorTable::iterator iter = table->begin();
+    SectorTable::iterator end = table->end();
+
+    for (uint64_t i = 0; i < size; i++) {
+        if (iter == end)
+            panic("Incorrect Table Size during save of COW disk image");
+
+        SafeWriteSwap(stream, (uint64_t)(*iter).first);
+        SafeWrite(stream, (*iter).second->data, sizeof(Sector));
+        ++iter;
+    }
+
+    stream.close();
+}
+
+void
+CowDiskImage::writeback()
+{
+    SectorTable::iterator i = table->begin();
+    SectorTable::iterator end = table->end();
+
+    while (i != end) {
+        child->write((*i).second->data, (*i).first);
+        ++i;
+    }
+}
+
+std::streampos
+CowDiskImage::size() const
+{ return child->size(); }
+
+std::streampos
+CowDiskImage::read(uint8_t *data, std::streampos offset) const
+{
+    if (!initialized)
+        panic("CowDiskImage not initialized");
+
+    if (offset > size())
+        panic("access out of bounds");
+
+    SectorTable::const_iterator i = table->find(offset);
+    if (i == table->end())
+        return child->read(data, offset);
+    else {
+        memcpy(data, (*i).second->data, SectorSize);
+        DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
+        DDUMP(DiskImageRead, data, SectorSize);
+        return SectorSize;
+    }
+}
+
+std::streampos
+CowDiskImage::write(const uint8_t *data, std::streampos offset)
+{
+    if (!initialized)
+        panic("RawDiskImage not initialized");
+
+    if (offset > size())
+        panic("access out of bounds");
+
+    SectorTable::iterator i = table->find(offset);
+    if (i == table->end()) {
+        Sector *sector = new Sector;
+        memcpy(sector, data, SectorSize);
+        table->insert(make_pair(offset, sector));
+    } else {
+        memcpy((*i).second->data, data, SectorSize);
+    }
+
+    DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
+    DDUMP(DiskImageWrite, data, SectorSize);
+
+    return SectorSize;
+}
+
+void
+CowDiskImage::serialize(CheckpointOut &cp) const
+{
+    string cowFilename = name() + ".cow";
+    SERIALIZE_SCALAR(cowFilename);
+    save(CheckpointIn::dir() + "/" + cowFilename);
+}
+
+void
+CowDiskImage::unserialize(CheckpointIn &cp)
+{
+    string cowFilename;
+    UNSERIALIZE_SCALAR(cowFilename);
+    cowFilename = cp.cptDir + "/" + cowFilename;
+    open(cowFilename);
+}
+
+CowDiskImage *
+CowDiskImageParams::create()
+{
+    return new CowDiskImage(this);
+}
diff --git a/src/dev/storage/disk_image.hh b/src/dev/storage/disk_image.hh
new file mode 100644 (file)
index 0000000..43e6adf
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+/** @file
+ * Disk Image Interfaces
+ */
+
+#ifndef __DEV_STORAGE_DISK_IMAGE_HH__
+#define __DEV_STORAGE_DISK_IMAGE_HH__
+
+#include <fstream>
+#include <unordered_map>
+
+#include "params/CowDiskImage.hh"
+#include "params/DiskImage.hh"
+#include "params/RawDiskImage.hh"
+#include "sim/sim_object.hh"
+
+#define SectorSize (512)
+
+/**
+ * Basic interface for accessing a disk image.
+ */
+class DiskImage : public SimObject
+{
+  protected:
+    bool initialized;
+
+  public:
+    typedef DiskImageParams Params;
+    DiskImage(const Params *p) : SimObject(p), initialized(false) {}
+    virtual ~DiskImage() {}
+
+    virtual std::streampos size() const = 0;
+
+    virtual std::streampos read(uint8_t *data,
+                                std::streampos offset) const = 0;
+    virtual std::streampos write(const uint8_t *data,
+                                 std::streampos offset) = 0;
+};
+
+/**
+ * Specialization for accessing a raw disk image
+ */
+class RawDiskImage : public DiskImage
+{
+  protected:
+    mutable std::fstream stream;
+    std::string file;
+    bool readonly;
+    mutable std::streampos disk_size;
+
+  public:
+    typedef RawDiskImageParams Params;
+    RawDiskImage(const Params *p);
+    ~RawDiskImage();
+
+    void close();
+    void open(const std::string &filename, bool rd_only = false);
+
+    virtual std::streampos size() const;
+
+    virtual std::streampos read(uint8_t *data, std::streampos offset) const;
+    virtual std::streampos write(const uint8_t *data, std::streampos offset);
+};
+
+/**
+ * Specialization for accessing a copy-on-write disk image layer.
+ * A copy-on-write(COW) layer must be stacked on top of another disk
+ * image layer this layer can be another CowDiskImage, or a
+ * RawDiskImage.
+ *
+ * This object is designed to provide a mechanism for persistant
+ * changes to a main disk image, or to provide a place for temporary
+ * changes to the image to take place that later may be thrown away.
+ */
+class CowDiskImage : public DiskImage
+{
+  public:
+    static const uint32_t VersionMajor;
+    static const uint32_t VersionMinor;
+
+  protected:
+    struct Sector {
+        uint8_t data[SectorSize];
+    };
+    typedef std::unordered_map<uint64_t, Sector *> SectorTable;
+
+  protected:
+    std::string filename;
+    DiskImage *child;
+    SectorTable *table;
+
+  public:
+    typedef CowDiskImageParams Params;
+    CowDiskImage(const Params *p);
+    ~CowDiskImage();
+
+    void initSectorTable(int hash_size);
+    bool open(const std::string &file);
+    void save() const;
+    void save(const std::string &file) const;
+    void writeback();
+
+    void serialize(CheckpointOut &cp) const override;
+    void unserialize(CheckpointIn &cp) override;
+
+    std::streampos size() const override;
+
+    std::streampos read(uint8_t *data, std::streampos offset) const override;
+    std::streampos write(const uint8_t *data, std::streampos offset) override;
+};
+
+void SafeRead(std::ifstream &stream, void *data, int count);
+
+template<class T>
+void SafeRead(std::ifstream &stream, T &data);
+
+template<class T>
+void SafeReadSwap(std::ifstream &stream, T &data);
+
+void SafeWrite(std::ofstream &stream, const void *data, int count);
+
+template<class T>
+void SafeWrite(std::ofstream &stream, const T &data);
+
+template<class T>
+void SafeWriteSwap(std::ofstream &stream, const T &data);
+
+#endif // __DEV_STORAGE_DISK_IMAGE_HH__
diff --git a/src/dev/storage/ide_atareg.h b/src/dev/storage/ide_atareg.h
new file mode 100644 (file)
index 0000000..51c8aec
--- /dev/null
@@ -0,0 +1,293 @@
+/*     $OpenBSD: atareg.h,v 1.12 2004/09/24 07:15:22 grange Exp $      */
+/*     $NetBSD: atareg.h,v 1.5 1999/01/18 20:06:24 bouyer Exp $        */
+
+/*
+ * Copyright (c) 1998, 2001 Manuel Bouyer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Manuel Bouyer.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DEV_ATA_ATAREG_H_
+#define _DEV_ATA_ATAREG_H_
+
+#if defined(__linux__)
+#include <endian.h>
+
+#elif defined(__sun)
+#include <sys/isa_defs.h>
+
+#else
+#include <machine/endian.h>
+
+#endif
+
+#ifdef LITTLE_ENDIAN
+#define ATA_BYTE_ORDER LITTLE_ENDIAN
+#elif defined(BIG_ENDIAN)
+#define ATA_BYTE_ORDER BIG_ENDIAN
+#elif defined(_LITTLE_ENDIAN)
+#define ATA_BYTE_ORDER 1
+#define LITTLE_ENDIAN 1
+#elif defined(_BIG_ENDIAN)
+#define ATA_BYTE_ORDER 0
+#define LITTLE_ENDIAN 1
+#else
+#error "No endianess defined"
+#endif
+
+/*
+ * Drive parameter structure for ATA/ATAPI.
+ * Bit fields: WDC_* : common to ATA/ATAPI
+ *             ATA_* : ATA only
+ *             ATAPI_* : ATAPI only.
+ */
+struct ataparams {
+    /* drive info */
+    uint16_t   atap_config;            /* 0: general configuration */
+#define WDC_CFG_ATAPI_MASK             0xc000
+#define WDC_CFG_ATAPI                  0x8000
+#define ATA_CFG_REMOVABLE              0x0080
+#define ATA_CFG_FIXED                  0x0040
+#define ATAPI_CFG_TYPE_MASK            0x1f00
+#define ATAPI_CFG_TYPE(x)              (((x) & ATAPI_CFG_TYPE_MASK) >> 8)
+#define ATAPI_CFG_TYPE_DIRECT          0x00
+#define ATAPI_CFG_TYPE_SEQUENTIAL      0x01
+#define ATAPI_CFG_TYPE_CDROM           0x05
+#define ATAPI_CFG_TYPE_OPTICAL         0x07
+#define ATAPI_CFG_TYPE_NODEVICE                0x1F
+#define ATAPI_CFG_REMOV                        0x0080
+#define ATAPI_CFG_DRQ_MASK             0x0060
+#define ATAPI_CFG_STD_DRQ              0x0000
+#define ATAPI_CFG_IRQ_DRQ              0x0020
+#define ATAPI_CFG_ACCEL_DRQ            0x0040
+#define ATAPI_CFG_CMD_MASK             0x0003
+#define ATAPI_CFG_CMD_12               0x0000
+#define ATAPI_CFG_CMD_16               0x0001
+/* words 1-9 are ATA only */
+    uint16_t   atap_cylinders;         /* 1: # of non-removable cylinders */
+    uint16_t   __reserved1;
+    uint16_t   atap_heads;             /* 3: # of heads */
+    uint16_t   __retired1[2];          /* 4-5: # of unform. bytes/track */
+    uint16_t   atap_sectors;           /* 6: # of sectors */
+    uint16_t   __retired2[3];
+
+    uint8_t    atap_serial[20];        /* 10-19: serial number */
+    uint16_t   __retired3[2];
+    uint16_t   __obsolete1;
+    uint8_t    atap_revision[8];       /* 23-26: firmware revision */
+    uint8_t    atap_model[40];         /* 27-46: model number */
+    uint16_t   atap_multi;             /* 47: maximum sectors per irq (ATA) */
+    uint16_t   __reserved2;
+    uint8_t    atap_vendor;            /* 49: vendor  */
+    uint8_t    atap_capabilities1;     /* 49: capability flags */
+#define WDC_CAP_IORDY  0x0800
+#define WDC_CAP_IORDY_DSBL 0x0400
+#define WDC_CAP_LBA    0x0200
+#define WDC_CAP_DMA    0x0100
+#define ATA_CAP_STBY   0x2000
+#define ATAPI_CAP_INTERL_DMA   0x8000
+#define ATAPI_CAP_CMD_QUEUE    0x4000
+#define ATAPI_CAP_OVERLP       0x2000
+#define ATAPI_CAP_ATA_RST      0x1000
+    uint16_t   atap_capabilities2;     /* 50: capability flags (ATA) */
+#if ATA_BYTE_ORDER == LITTLE_ENDIAN
+    uint8_t    __junk2;
+    uint8_t    atap_oldpiotiming;      /* 51: old PIO timing mode */
+    uint8_t    __junk3;
+    uint8_t    atap_olddmatiming;      /* 52: old DMA timing mode (ATA) */
+#else
+    uint8_t    atap_oldpiotiming;      /* 51: old PIO timing mode */
+    uint8_t    __junk2;
+    uint8_t    atap_olddmatiming;      /* 52: old DMA timing mode (ATA) */
+    uint8_t    __junk3;
+#endif
+    uint16_t   atap_extensions;        /* 53: extensions supported */
+#define WDC_EXT_UDMA_MODES     0x0004
+#define WDC_EXT_MODES          0x0002
+#define WDC_EXT_GEOM           0x0001
+/* words 54-62 are ATA only */
+    uint16_t   atap_curcylinders;      /* 54: current logical cylinders */
+    uint16_t   atap_curheads;          /* 55: current logical heads */
+    uint16_t   atap_cursectors;        /* 56: current logical sectors/tracks */
+    uint16_t   atap_curcapacity[2];    /* 57-58: current capacity */
+    uint8_t    atap_curmulti;          /* 59: current multi-sector setting */
+    uint8_t    atap_curmulti_valid;    /* 59: current multi-sector setting */
+#define WDC_MULTI_VALID 0x0100
+#define WDC_MULTI_MASK  0x00ff
+    uint32_t   atap_capacity;  /* 60-61: total capacity (LBA only) */
+    uint16_t   __retired4;
+#if ATA_BYTE_ORDER == LITTLE_ENDIAN
+    uint8_t    atap_dmamode_supp;      /* 63: multiword DMA mode supported */
+    uint8_t    atap_dmamode_act;       /*     multiword DMA mode active */
+    uint8_t    atap_piomode_supp;      /* 64: PIO mode supported */
+    uint8_t    __junk4;
+#else
+    uint8_t    atap_dmamode_act;       /*     multiword DMA mode active */
+    uint8_t    atap_dmamode_supp;      /* 63: multiword DMA mode supported */
+    uint8_t    __junk4;
+    uint8_t    atap_piomode_supp;      /* 64: PIO mode supported */
+#endif
+    uint16_t   atap_dmatiming_mimi;    /* 65: minimum DMA cycle time */
+    uint16_t   atap_dmatiming_recom;   /* 66: recommended DMA cycle time */
+    uint16_t   atap_piotiming;         /* 67: mini PIO cycle time without FC */
+    uint16_t   atap_piotiming_iordy;   /* 68: mini PIO cycle time with IORDY FC */
+    uint16_t   __reserved3[2];
+/* words 71-72 are ATAPI only */
+    uint16_t   atap_pkt_br;            /* 71: time (ns) to bus release */
+    uint16_t   atap_pkt_bsyclr;        /* 72: tme to clear BSY after service */
+    uint16_t   __reserved4[2];
+    uint16_t   atap_queuedepth;        /* 75: */
+#define WDC_QUEUE_DEPTH_MASK 0x1f
+    uint16_t   atap_sata_caps;         /* 76: SATA capabilities */
+#define SATA_SIGNAL_GEN1       0x0002  /* SATA Gen-1 signaling speed */
+#define SATA_SIGNAL_GEN2       0x0004  /* SATA Gen-2 signaling speed */
+#define SATA_NATIVE_CMDQ       0x0100  /* native command queuing */
+#define SATA_HOST_PWR_MGMT     0x0200  /* power management (host) */
+    uint16_t   atap_sata_reserved;     /* 77: reserved */
+    uint16_t   atap_sata_features_supp;/* 78: SATA features supported */
+#define SATA_NONZERO_OFFSETS   0x0002  /* non-zero buffer offsets */
+#define SATA_DMA_SETUP_AUTO    0x0004  /* DMA setup auto-activate */
+#define SATA_DRIVE_PWR_MGMT    0x0008  /* power management (device) */
+    uint16_t   atap_sata_features_en;  /* 79: SATA features enabled */
+    uint16_t   atap_ata_major;         /* 80: Major version number */
+#define WDC_VER_ATA1   0x0002
+#define WDC_VER_ATA2   0x0004
+#define WDC_VER_ATA3   0x0008
+#define WDC_VER_ATA4   0x0010
+#define WDC_VER_ATA5   0x0020
+#define WDC_VER_ATA6   0x0040
+#define WDC_VER_ATA7   0x0080
+#define WDC_VER_ATA8   0x0100
+#define WDC_VER_ATA9   0x0200
+#define WDC_VER_ATA10  0x0400
+#define WDC_VER_ATA11  0x0800
+#define WDC_VER_ATA12  0x1000
+#define WDC_VER_ATA13  0x2000
+#define WDC_VER_ATA14  0x4000
+    uint16_t   atap_ata_minor;         /* 81: Minor version number */
+    uint16_t   atap_cmd_set1;          /* 82: command set supported */
+#define WDC_CMD1_NOP   0x4000
+#define WDC_CMD1_RB    0x2000
+#define WDC_CMD1_WB    0x1000
+#define WDC_CMD1_HPA   0x0400
+#define WDC_CMD1_DVRST 0x0200
+#define WDC_CMD1_SRV   0x0100
+#define WDC_CMD1_RLSE  0x0080
+#define WDC_CMD1_AHEAD 0x0040
+#define WDC_CMD1_CACHE 0x0020
+#define WDC_CMD1_PKT   0x0010
+#define WDC_CMD1_PM    0x0008
+#define WDC_CMD1_REMOV 0x0004
+#define WDC_CMD1_SEC   0x0002
+#define WDC_CMD1_SMART 0x0001
+    uint16_t   atap_cmd_set2;          /* 83: command set supported */
+#define ATAPI_CMD2_FCE 0x2000 /* Flush Cache Ext supported */
+#define ATAPI_CMD2_FC  0x1000 /* Flush Cache supported */
+#define ATAPI_CMD2_DCO 0x0800 /* Device Configuration Overlay supported */
+#define ATAPI_CMD2_48AD        0x0400 /* 48bit address supported */
+#define ATAPI_CMD2_AAM 0x0200 /* Automatic Acoustic Management supported */
+#define ATAPI_CMD2_SM  0x0100 /* Set Max security extension supported */
+#define ATAPI_CMD2_SF  0x0040 /* Set Features subcommand required */
+#define ATAPI_CMD2_PUIS        0x0020 /* Power up in standby supported */
+#define WDC_CMD2_RMSN  0x0010
+#define ATA_CMD2_APM   0x0008
+#define ATA_CMD2_CFA   0x0004
+#define ATA_CMD2_RWQ   0x0002
+#define WDC_CMD2_DM    0x0001 /* Download Microcode supported */
+    uint16_t   atap_cmd_ext;           /* 84: command/features supp. ext. */
+#define ATAPI_CMDE_MSER        0x0004 /* Media serial number supported */
+#define ATAPI_CMDE_TEST        0x0002 /* SMART self-test supported */
+#define ATAPI_CMDE_SLOG        0x0001 /* SMART error logging supported */
+    uint16_t   atap_cmd1_en;           /* 85: cmd/features enabled */
+/* bits are the same as atap_cmd_set1 */
+    uint16_t   atap_cmd2_en;           /* 86: cmd/features enabled */
+/* bits are the same as atap_cmd_set2 */
+    uint16_t   atap_cmd_def;           /* 87: cmd/features default */
+/* bits are NOT the same as atap_cmd_ext */
+#if ATA_BYTE_ORDER == LITTLE_ENDIAN
+    uint8_t    atap_udmamode_supp;     /* 88: Ultra-DMA mode supported */
+    uint8_t    atap_udmamode_act;      /*     Ultra-DMA mode active */
+#else
+    uint8_t    atap_udmamode_act;      /*     Ultra-DMA mode active */
+    uint8_t    atap_udmamode_supp;     /* 88: Ultra-DMA mode supported */
+#endif
+/* 89-92 are ATA-only */
+    uint16_t   atap_seu_time;          /* 89: Sec. Erase Unit compl. time */
+    uint16_t   atap_eseu_time;         /* 90: Enhanced SEU compl. time */
+    uint16_t   atap_apm_val;           /* 91: current APM value */
+    uint16_t   atap_mpasswd_rev;       /* 92: Master Password revision */
+    uint16_t   atap_hwreset_res;       /* 93: Hardware reset value */
+#define ATA_HWRES_CBLID    0x2000  /* CBLID above Vih */
+#define ATA_HWRES_D1_PDIAG 0x0800  /* Device 1 PDIAG detect OK */
+#define ATA_HWRES_D1_CSEL  0x0400  /* Device 1 used CSEL for address */
+#define ATA_HWRES_D1_JUMP  0x0200  /* Device 1 jumpered to address */
+#define ATA_HWRES_D0_SEL   0x0040  /* Device 0 responds when Dev 1 selected */
+#define ATA_HWRES_D0_DASP  0x0020  /* Device 0 DASP detect OK */
+#define ATA_HWRES_D0_PDIAG 0x0010  /* Device 0 PDIAG detect OK */
+#define ATA_HWRES_D0_DIAG  0x0008  /* Device 0 diag OK */
+#define ATA_HWRES_D0_CSEL  0x0004  /* Device 0 used CSEL for address */
+#define ATA_HWRES_D0_JUMP  0x0002  /* Device 0 jumpered to address */
+#if ATA_BYTE_ORDER == LITTLE_ENDIAN
+    uint8_t    atap_acoustic_val;      /* 94: Current acoustic level */
+    uint8_t    atap_acoustic_def;      /*     recommended level */
+#else
+    uint8_t    atap_acoustic_def;      /*     recommended level */
+    uint8_t    atap_acoustic_val;      /* 94: Current acoustic level */
+#endif
+    uint16_t   __reserved6[5];         /* 95-99: reserved */
+    uint16_t   atap_max_lba[4];        /* 100-103: Max. user LBA add */
+    uint16_t   __reserved7[23];        /* 104-126: reserved */
+    uint16_t   atap_rmsn_supp;         /* 127: remov. media status notif. */
+#define WDC_RMSN_SUPP_MASK 0x0003
+#define WDC_RMSN_SUPP 0x0001
+    uint16_t   atap_sec_st;            /* 128: security status */
+#define WDC_SEC_LEV_MAX        0x0100
+#define WDC_SEC_ESE_SUPP 0x0020
+#define WDC_SEC_EXP    0x0010
+#define WDC_SEC_FROZEN 0x0008
+#define WDC_SEC_LOCKED 0x0004
+#define WDC_SEC_EN     0x0002
+#define WDC_SEC_SUPP   0x0001
+    uint16_t   __reserved8[31];        /* 129-159: vendor specific */
+    uint16_t   atap_cfa_power;         /* 160: CFA powermode */
+#define ATAPI_CFA_MAX_MASK  0x0FFF
+#define ATAPI_CFA_MODE1_DIS 0x1000 /* CFA Mode 1 Disabled */
+#define ATAPI_CFA_MODE1_REQ 0x2000 /* CFA Mode 1 Required */
+#define ATAPI_CFA_WORD160   0x8000 /* Word 160 supported */
+    uint16_t   __reserved9[15];        /* 161-175: reserved for CFA */
+    uint8_t    atap_media_serial[60];  /* 176-205: media serial number */
+    uint16_t   __reserved10[49];       /* 206-254: reserved */
+#if ATA_BYTE_ORDER == LITTLE_ENDIAN
+    uint8_t    atap_signature;         /* 255: Signature */
+    uint8_t    atap_checksum;          /*      Checksum */
+#else
+    uint8_t    atap_checksum;          /*      Checksum */
+    uint8_t    atap_signature;         /* 255: Signature */
+#endif
+};
+
+#undef ATA_BYTE_ORDER
+#endif /* !_DEV_ATA_ATAREG_H_ */
diff --git a/src/dev/storage/ide_ctrl.cc b/src/dev/storage/ide_ctrl.cc
new file mode 100644 (file)
index 0000000..feed9cf
--- /dev/null
@@ -0,0 +1,650 @@
+/*
+ * 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Andrew Schultz
+ *          Ali Saidi
+ *          Miguel Serrano
+ */
+
+#include "dev/storage/ide_ctrl.hh"
+
+#include <string>
+
+#include "cpu/intr_control.hh"
+#include "debug/IdeCtrl.hh"
+#include "dev/storage/ide_disk.hh"
+#include "mem/packet.hh"
+#include "mem/packet_access.hh"
+#include "params/IdeController.hh"
+#include "sim/byteswap.hh"
+
+// 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 {
+    BMICommand = 0x0,
+    BMIStatus = 0x2,
+    BMIDescTablePtr = 0x4
+};
+
+// PCI config space registers
+enum ConfRegOffset {
+    PrimaryTiming = 0x40,
+    SecondaryTiming = 0x42,
+    DeviceTiming = 0x44,
+    UDMAControl = 0x48,
+    UDMATiming = 0x4A,
+    IDEConfig = 0x54
+};
+
+static const uint16_t timeRegWithDecodeEn = 0x8000;
+
+IdeController::Channel::Channel(
+        string newName, Addr _cmdSize, Addr _ctrlSize) :
+    _name(newName),
+    cmdAddr(0), cmdSize(_cmdSize), ctrlAddr(0), ctrlSize(_ctrlSize),
+    master(NULL), slave(NULL), selected(NULL)
+{
+    memset(&bmiRegs, 0, sizeof(bmiRegs));
+    bmiRegs.status.dmaCap0 = 1;
+    bmiRegs.status.dmaCap1 = 1;
+}
+
+IdeController::Channel::~Channel()
+{
+}
+
+IdeController::IdeController(Params *p)
+    : 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),
+    ioShift(p->io_shift), ctrlOffset(p->ctrl_offset)
+{
+    if (params()->disks.size() > 3)
+        panic("IDE controllers support a maximum of 4 devices attached!\n");
+
+    // Assign the disks to channels
+    int numDisks = params()->disks.size();
+    if (numDisks > 0)
+        primary.master = params()->disks[0];
+    if (numDisks > 1)
+        primary.slave = params()->disks[1];
+    if (numDisks > 2)
+        secondary.master = params()->disks[2];
+    if (numDisks > 3)
+        secondary.slave = params()->disks[3];
+
+    for (int i = 0; i < params()->disks.size(); i++) {
+        params()->disks[i]->setController(this);
+    }
+    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
+IdeController::isDiskSelected(IdeDisk *diskPtr)
+{
+    return (primary.selected == diskPtr || secondary.selected == diskPtr);
+}
+
+void
+IdeController::intrPost()
+{
+    primary.bmiRegs.status.intStatus = 1;
+    PciDevice::intrPost();
+}
+
+void
+IdeController::setDmaComplete(IdeDisk *disk)
+{
+    Channel *channel;
+    if (disk == primary.master || disk == primary.slave) {
+        channel = &primary;
+    } else if (disk == secondary.master || disk == secondary.slave) {
+        channel = &secondary;
+    } else {
+        panic("Unable to find disk based on pointer %#x\n", disk);
+    }
+
+    channel->bmiRegs.command.startStop = 0;
+    channel->bmiRegs.status.active = 0;
+    channel->bmiRegs.status.intStatus = 1;
+}
+
+Tick
+IdeController::readConfig(PacketPtr pkt)
+{
+    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
+    if (offset < PCI_DEVICE_SPECIFIC) {
+        return PciDevice::readConfig(pkt);
+    }
+
+    switch (pkt->getSize()) {
+      case sizeof(uint8_t):
+        switch (offset) {
+          case DeviceTiming:
+            pkt->set<uint8_t>(deviceTiming);
+            break;
+          case UDMAControl:
+            pkt->set<uint8_t>(udmaControl);
+            break;
+          case PrimaryTiming + 1:
+            pkt->set<uint8_t>(bits(htole(primaryTiming), 15, 8));
+            break;
+          case SecondaryTiming + 1:
+            pkt->set<uint8_t>(bits(htole(secondaryTiming), 15, 8));
+            break;
+          case IDEConfig:
+            pkt->set<uint8_t>(bits(htole(ideConfig), 7, 0));
+            break;
+          case IDEConfig + 1:
+            pkt->set<uint8_t>(bits(htole(ideConfig), 15, 8));
+            break;
+          default:
+            panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
+                    offset);
+        }
+        DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", offset,
+                (uint32_t)pkt->get<uint8_t>());
+        break;
+      case sizeof(uint16_t):
+        switch (offset) {
+          case UDMAControl:
+            pkt->set<uint16_t>(udmaControl);
+            break;
+          case PrimaryTiming:
+            pkt->set<uint16_t>(primaryTiming);
+            break;
+          case SecondaryTiming:
+            pkt->set<uint16_t>(secondaryTiming);
+            break;
+          case UDMATiming:
+            pkt->set<uint16_t>(udmaTiming);
+            break;
+          case IDEConfig:
+            pkt->set<uint16_t>(ideConfig);
+            break;
+          default:
+            panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
+                    offset);
+        }
+        DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset,
+                (uint32_t)pkt->get<uint16_t>());
+        break;
+      case sizeof(uint32_t):
+        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;
+      default:
+        panic("invalid access size(?) for PCI configspace!\n");
+    }
+    pkt->makeAtomicResponse();
+    return configDelay;
+}
+
+
+Tick
+IdeController::writeConfig(PacketPtr pkt)
+{
+    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
+    if (offset < PCI_DEVICE_SPECIFIC) {
+        PciDevice::writeConfig(pkt);
+    } else {
+        switch (pkt->getSize()) {
+          case sizeof(uint8_t):
+            switch (offset) {
+              case DeviceTiming:
+                deviceTiming = pkt->get<uint8_t>();
+                break;
+              case UDMAControl:
+                udmaControl = pkt->get<uint8_t>();
+                break;
+              case IDEConfig:
+                replaceBits(ideConfig, 7, 0, pkt->get<uint8_t>());
+                break;
+              case IDEConfig + 1:
+                replaceBits(ideConfig, 15, 8, pkt->get<uint8_t>());
+                break;
+              default:
+                panic("Invalid PCI configuration write "
+                        "for size 1 offset: %#x!\n", offset);
+            }
+            DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n",
+                    offset, (uint32_t)pkt->get<uint8_t>());
+            break;
+          case sizeof(uint16_t):
+            switch (offset) {
+              case UDMAControl:
+                udmaControl = pkt->get<uint16_t>();
+                break;
+              case PrimaryTiming:
+                primaryTiming = pkt->get<uint16_t>();
+                break;
+              case SecondaryTiming:
+                secondaryTiming = pkt->get<uint16_t>();
+                break;
+              case UDMATiming:
+                udmaTiming = pkt->get<uint16_t>();
+                break;
+              case IDEConfig:
+                ideConfig = pkt->get<uint16_t>();
+                break;
+              default:
+                panic("Invalid PCI configuration write "
+                        "for size 2 offset: %#x!\n",
+                        offset);
+            }
+            DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n",
+                    offset, (uint32_t)pkt->get<uint16_t>());
+            break;
+          case sizeof(uint32_t):
+            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");
+        }
+        pkt->makeAtomicResponse();
+    }
+
+    /* Trap command register writes and enable IO/BM as appropriate as well as
+     * BARs. */
+    switch(offset) {
+      case PCI0_BASE_ADDR0:
+        if (BARAddrs[0] != 0)
+            primary.cmdAddr = BARAddrs[0];
+        break;
+
+      case PCI0_BASE_ADDR1:
+        if (BARAddrs[1] != 0)
+            primary.ctrlAddr = BARAddrs[1];
+        break;
+
+      case PCI0_BASE_ADDR2:
+        if (BARAddrs[2] != 0)
+            secondary.cmdAddr = BARAddrs[2];
+        break;
+
+      case PCI0_BASE_ADDR3:
+        if (BARAddrs[3] != 0)
+            secondary.ctrlAddr = BARAddrs[3];
+        break;
+
+      case PCI0_BASE_ADDR4:
+        if (BARAddrs[4] != 0)
+            bmiAddr = BARAddrs[4];
+        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;
+    }
+    return configDelay;
+}
+
+void
+IdeController::Channel::accessCommand(Addr offset,
+        int size, uint8_t *data, bool read)
+{
+    const Addr SelectOffset = 6;
+    const uint8_t SelectDevBit = 0x10;
+
+    if (!read && offset == SelectOffset)
+        select(*data & SelectDevBit);
+
+    if (selected == NULL) {
+        assert(size == sizeof(uint8_t));
+        *data = 0;
+    } else if (read) {
+        selected->readCommand(offset, size, data);
+    } else {
+        selected->writeCommand(offset, size, data);
+    }
+}
+
+void
+IdeController::Channel::accessControl(Addr offset,
+        int size, uint8_t *data, bool read)
+{
+    if (selected == NULL) {
+        assert(size == sizeof(uint8_t));
+        *data = 0;
+    } else if (read) {
+        selected->readControl(offset, size, data);
+    } else {
+        selected->writeControl(offset, size, data);
+    }
+}
+
+void
+IdeController::Channel::accessBMI(Addr offset,
+        int size, uint8_t *data, bool read)
+{
+    assert(offset + size <= sizeof(BMIRegs));
+    if (read) {
+        memcpy(data, (uint8_t *)&bmiRegs + offset, size);
+    } else {
+        switch (offset) {
+          case BMICommand:
+            {
+                if (size != sizeof(uint8_t))
+                    panic("Invalid BMIC write size: %x\n", size);
+
+                BMICommandReg oldVal = bmiRegs.command;
+                BMICommandReg newVal = *data;
+
+                // if a DMA transfer is in progress, R/W control cannot change
+                if (oldVal.startStop && oldVal.rw != newVal.rw)
+                    oldVal.rw = newVal.rw;
+
+                if (oldVal.startStop != newVal.startStop) {
+                    if (selected == NULL)
+                        panic("DMA start for disk which does not exist\n");
+
+                    if (oldVal.startStop) {
+                        DPRINTF(IdeCtrl, "Stopping DMA transfer\n");
+                        bmiRegs.status.active = 0;
+
+                        selected->abortDma();
+                    } else {
+                        DPRINTF(IdeCtrl, "Starting DMA transfer\n");
+                        bmiRegs.status.active = 1;
+
+                        selected->startDma(letoh(bmiRegs.bmidtp));
+                    }
+                }
+
+                bmiRegs.command = newVal;
+            }
+            break;
+          case BMIStatus:
+            {
+                if (size != sizeof(uint8_t))
+                    panic("Invalid BMIS write size: %x\n", size);
+
+                BMIStatusReg oldVal = bmiRegs.status;
+                BMIStatusReg newVal = *data;
+
+                // the BMIDEA bit is read only
+                newVal.active = oldVal.active;
+
+                // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
+                if ((oldVal.intStatus == 1) && (newVal.intStatus == 1)) {
+                    newVal.intStatus = 0; // clear the interrupt?
+                } 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 {
+                    uint8_t tmp = oldVal.dmaError;
+                    newVal.dmaError = tmp;
+                }
+
+                bmiRegs.status = newVal;
+            }
+            break;
+          case BMIDescTablePtr:
+            if (size != sizeof(uint32_t))
+                panic("Invalid BMIDTP write size: %x\n", size);
+            bmiRegs.bmidtp = htole(*(uint32_t *)data & ~0x3);
+            break;
+          default:
+            if (size != sizeof(uint8_t) && size != sizeof(uint16_t) &&
+                    size != sizeof(uint32_t))
+                panic("IDE controller write of invalid write size: %x\n", size);
+            memcpy((uint8_t *)&bmiRegs + offset, data, size);
+        }
+    }
+}
+
+void
+IdeController::dispatchAccess(PacketPtr pkt, bool read)
+{
+    if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4)
+         panic("Bad IDE read size: %d\n", pkt->getSize());
+
+    if (!ioEnabled) {
+        pkt->makeAtomicResponse();
+        DPRINTF(IdeCtrl, "io not enabled\n");
+        return;
+    }
+
+    Addr addr = pkt->getAddr();
+    int size = pkt->getSize();
+    uint8_t *dataPtr = pkt->getPtr<uint8_t>();
+
+    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)) {
+        addr -= secondary.cmdAddr;
+        secondary.accessCommand(addr, size, dataPtr, read);
+    } else if (addr >= secondary.ctrlAddr &&
+               addr < (secondary.ctrlAddr + secondary.ctrlSize)) {
+        addr -= secondary.ctrlAddr;
+        secondary.accessControl(addr, size, dataPtr, read);
+    } else if (addr >= bmiAddr && addr < (bmiAddr + bmiSize)) {
+        if (!read && !bmEnabled)
+            return;
+        addr -= bmiAddr;
+        if (addr < sizeof(Channel::BMIRegs)) {
+            primary.accessBMI(addr, size, dataPtr, read);
+        } else {
+            addr -= sizeof(Channel::BMIRegs);
+            secondary.accessBMI(addr, size, dataPtr, read);
+        }
+    } else {
+        panic("IDE controller access to invalid address: %#x\n", addr);
+    }
+
+#ifndef NDEBUG
+    uint32_t data;
+    if (pkt->getSize() == 1)
+        data = pkt->get<uint8_t>();
+    else if (pkt->getSize() == 2)
+        data = pkt->get<uint16_t>();
+    else
+        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();
+}
+
+Tick
+IdeController::read(PacketPtr pkt)
+{
+    dispatchAccess(pkt, true);
+    return pioDelay;
+}
+
+Tick
+IdeController::write(PacketPtr pkt)
+{
+    dispatchAccess(pkt, false);
+    return pioDelay;
+}
+
+void
+IdeController::serialize(CheckpointOut &cp) const
+{
+    // Serialize the PciDevice base class
+    PciDevice::serialize(cp);
+
+    // Serialize channels
+    primary.serialize("primary", cp);
+    secondary.serialize("secondary", cp);
+
+    // Serialize config registers
+    SERIALIZE_SCALAR(primaryTiming);
+    SERIALIZE_SCALAR(secondaryTiming);
+    SERIALIZE_SCALAR(deviceTiming);
+    SERIALIZE_SCALAR(udmaControl);
+    SERIALIZE_SCALAR(udmaTiming);
+    SERIALIZE_SCALAR(ideConfig);
+
+    // Serialize internal state
+    SERIALIZE_SCALAR(ioEnabled);
+    SERIALIZE_SCALAR(bmEnabled);
+    SERIALIZE_SCALAR(bmiAddr);
+    SERIALIZE_SCALAR(bmiSize);
+}
+
+void
+IdeController::Channel::serialize(const std::string &base,
+                                  CheckpointOut &cp) const
+{
+    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(cp, base + ".bmiRegs.command", command);
+    paramOut(cp, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
+    uint8_t status = bmiRegs.status;
+    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(CheckpointIn &cp)
+{
+    // Unserialize the PciDevice base class
+    PciDevice::unserialize(cp);
+
+    // Unserialize channels
+    primary.unserialize("primary", cp);
+    secondary.unserialize("secondary", cp);
+
+    // Unserialize config registers
+    UNSERIALIZE_SCALAR(primaryTiming);
+    UNSERIALIZE_SCALAR(secondaryTiming);
+    UNSERIALIZE_SCALAR(deviceTiming);
+    UNSERIALIZE_SCALAR(udmaControl);
+    UNSERIALIZE_SCALAR(udmaTiming);
+    UNSERIALIZE_SCALAR(ideConfig);
+
+    // Unserialize internal state
+    UNSERIALIZE_SCALAR(ioEnabled);
+    UNSERIALIZE_SCALAR(bmEnabled);
+    UNSERIALIZE_SCALAR(bmiAddr);
+    UNSERIALIZE_SCALAR(bmiSize);
+}
+
+void
+IdeController::Channel::unserialize(const std::string &base, CheckpointIn &cp)
+{
+    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, base +".bmiRegs.command", command);
+    bmiRegs.command = command;
+    paramIn(cp, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
+    uint8_t status;
+    paramIn(cp, base + ".bmiRegs.status", status);
+    bmiRegs.status = status;
+    paramIn(cp, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
+    paramIn(cp, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
+    paramIn(cp, base + ".selectBit", selectBit);
+    select(selectBit);
+}
+
+IdeController *
+IdeControllerParams::create()
+{
+    return new IdeController(this);
+}
diff --git a/src/dev/storage/ide_ctrl.hh b/src/dev/storage/ide_ctrl.hh
new file mode 100644 (file)
index 0000000..94a9c65
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Andrew Schultz
+ *          Miguel Serrano
+ */
+
+/** @file
+ * Simple PCI IDE controller with bus mastering capability and UDMA
+ * modeled after controller in the Intel PIIX4 chip
+ */
+
+#ifndef __DEV_STORAGE_IDE_CTRL_HH__
+#define __DEV_STORAGE_IDE_CTRL_HH__
+
+#include "base/bitunion.hh"
+#include "dev/io_device.hh"
+#include "dev/pci/device.hh"
+#include "params/IdeController.hh"
+
+class IdeDisk;
+
+/**
+ * Device model for an Intel PIIX4 IDE controller
+ */
+
+class IdeController : public PciDevice
+{
+  private:
+    // Bus master IDE status register bit fields
+    BitUnion8(BMIStatusReg)
+        Bitfield<6> dmaCap0;
+        Bitfield<5> dmaCap1;
+        Bitfield<2> intStatus;
+        Bitfield<1> dmaError;
+        Bitfield<0> active;
+    EndBitUnion(BMIStatusReg)
+
+    BitUnion8(BMICommandReg)
+        Bitfield<3> rw;
+        Bitfield<0> startStop;
+    EndBitUnion(BMICommandReg)
+
+    struct Channel
+    {
+        std::string _name;
+
+        const std::string
+        name()
+        {
+            return _name;
+        }
+
+        /** Command and control block registers */
+        Addr cmdAddr, cmdSize, ctrlAddr, ctrlSize;
+
+        /** Registers used for bus master interface */
+        struct BMIRegs
+        {
+            BMICommandReg command;
+            uint8_t reserved0;
+            BMIStatusReg status;
+            uint8_t reserved1;
+            uint32_t bmidtp;
+        } bmiRegs;
+
+        /** IDE disks connected to this controller */
+        IdeDisk *master, *slave;
+
+        /** Currently selected disk */
+        IdeDisk *selected;
+
+        bool selectBit;
+
+        void
+        select(bool selSlave)
+        {
+            selectBit = selSlave;
+            selected = selectBit ? slave : master;
+        }
+
+        void accessCommand(Addr offset, int size, uint8_t *data, bool read);
+        void accessControl(Addr offset, int size, uint8_t *data, bool read);
+        void accessBMI(Addr offset, int size, uint8_t *data, bool read);
+
+        Channel(std::string newName, Addr _cmdSize, Addr _ctrlSize);
+        ~Channel();
+
+        void serialize(const std::string &base, std::ostream &os) const;
+        void unserialize(const std::string &base, CheckpointIn &cp);
+    };
+
+    Channel primary;
+    Channel secondary;
+
+    /** Bus master interface (BMI) registers */
+    Addr bmiAddr, bmiSize;
+
+    /** Registers used in device specific PCI configuration */
+    uint16_t primaryTiming, secondaryTiming;
+    uint8_t deviceTiming;
+    uint8_t udmaControl;
+    uint16_t udmaTiming;
+    uint16_t ideConfig;
+
+    // Internal management variables
+    bool ioEnabled;
+    bool bmEnabled;
+
+    uint32_t ioShift, ctrlOffset;
+
+    void dispatchAccess(PacketPtr pkt, bool read);
+
+  public:
+    typedef IdeControllerParams Params;
+    const Params *params() const { return (const Params *)_params; }
+    IdeController(Params *p);
+
+    /** See if a disk is selected based on its pointer */
+    bool isDiskSelected(IdeDisk *diskPtr);
+
+    void intrPost();
+
+    Tick writeConfig(PacketPtr pkt) override;
+    Tick readConfig(PacketPtr pkt) override;
+
+    void setDmaComplete(IdeDisk *disk);
+
+    Tick read(PacketPtr pkt) override;
+    Tick write(PacketPtr pkt) override;
+
+    void serialize(CheckpointOut &cp) const override;
+    void unserialize(CheckpointIn &cp) override;
+};
+#endif // __DEV_STORAGE_IDE_CTRL_HH_
diff --git a/src/dev/storage/ide_disk.cc b/src/dev/storage/ide_disk.cc
new file mode 100644 (file)
index 0000000..4eefdbb
--- /dev/null
@@ -0,0 +1,1203 @@
+/*
+ * 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Andrew Schultz
+ *          Ali Saidi
+ */
+
+/** @file
+ * Device model implementation for an IDE disk
+ */
+
+#include "dev/storage/ide_disk.hh"
+
+#include <cerrno>
+#include <cstring>
+#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/storage/disk_image.hh"
+#include "dev/storage/ide_ctrl.hh"
+#include "sim/core.hh"
+#include "sim/sim_object.hh"
+
+using namespace std;
+using namespace TheISA;
+
+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(p->driveID);
+
+    // fill out the drive ID structure
+    memset(&driveID, 0, sizeof(struct ataparams));
+
+    // Calculate LBA and C/H/S values
+    uint16_t cylinders;
+    uint8_t heads;
+    uint8_t sectors;
+
+    uint32_t lba_size = image->size();
+    if (lba_size >= 16383*16*63) {
+        cylinders = 16383;
+        heads = 16;
+        sectors = 63;
+    } else {
+        if (lba_size >= 63)
+            sectors = 63;
+        else if (lba_size == 0)
+            panic("Bad IDE image size: 0\n");
+        else
+            sectors = lba_size;
+
+        if ((lba_size / sectors) >= 16)
+            heads = 16;
+        else
+            heads = (lba_size / sectors);
+
+        cylinders = lba_size / (heads * sectors);
+    }
+
+    // Setup the model name
+    strncpy((char *)driveID.atap_model, "5MI EDD si k",
+            sizeof(driveID.atap_model));
+    // Set the maximum multisector transfer size
+    driveID.atap_multi = MAX_MULTSECT;
+    // IORDY supported, IORDY disabled, LBA enabled, DMA enabled
+    driveID.atap_capabilities1 = 0x7;
+    // UDMA support, EIDE support
+    driveID.atap_extensions = 0x6;
+    // Setup default C/H/S settings
+    driveID.atap_cylinders = cylinders;
+    driveID.atap_sectors = sectors;
+    driveID.atap_heads = heads;
+    // Setup the current multisector transfer size
+    driveID.atap_curmulti = MAX_MULTSECT;
+    driveID.atap_curmulti_valid = 0x1;
+    // Number of sectors on disk
+    driveID.atap_capacity = lba_size;
+    // Multiword DMA mode 2 and below supported
+    driveID.atap_dmamode_supp = 0x4;
+    // Set PIO mode 4 and 3 supported
+    driveID.atap_piomode_supp = 0x3;
+    // Set DMA mode 4 and below supported
+    driveID.atap_udmamode_supp = 0x1f;
+    // Statically set hardware config word
+    driveID.atap_hwreset_res = 0x4001;
+
+    //arbitrary for now...
+    driveID.atap_ata_major = WDC_VER_ATA7;
+}
+
+IdeDisk::~IdeDisk()
+{
+    // destroy the data buffer
+    delete [] dataBuffer;
+}
+
+void
+IdeDisk::reset(int id)
+{
+    // initialize the data buffer and shadow registers
+    dataBuffer = new uint8_t[MAX_DMA_SIZE];
+
+    memset(dataBuffer, 0, MAX_DMA_SIZE);
+    memset(&cmdReg, 0, sizeof(CommandReg_t));
+    memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
+
+    curPrdAddr = 0;
+    curSector = 0;
+    cmdBytes = 0;
+    cmdBytesLeft = 0;
+    drqBytesLeft = 0;
+    dmaRead = false;
+    intrPending = false;
+    dmaAborted = false;
+
+    // set the device state to idle
+    dmaState = Dma_Idle;
+
+    if (id == DEV0) {
+        devState = Device_Idle_S;
+        devID = DEV0;
+    } else if (id == DEV1) {
+        devState = Device_Idle_NS;
+        devID = DEV1;
+    } else {
+        panic("Invalid device ID: %#x\n", id);
+    }
+
+    // set the device ready bit
+    status = STATUS_DRDY_BIT;
+
+    /* The error register must be set to 0x1 on start-up to
+       indicate that no diagnostic error was detected */
+    cmdReg.error = 0x1;
+}
+
+////
+// Utility functions
+////
+
+bool
+IdeDisk::isDEVSelect()
+{
+    return ctrl->isDiskSelected(this);
+}
+
+Addr
+IdeDisk::pciToDma(Addr pciAddr)
+{
+    if (ctrl)
+        return ctrl->pciToDma(pciAddr);
+    else
+        panic("Access to unset controller!\n");
+}
+
+////
+// Device registers read/write
+////
+
+void
+IdeDisk::readCommand(const Addr offset, int size, uint8_t *data)
+{
+    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 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("Invalid IDE command register offset: %#x\n", offset);
+    }
+    DPRINTF(IdeDisk, "Read to disk at offset: %#x data %#x\n", offset, *data);
+}
+
+void
+IdeDisk::readControl(const Addr offset, int size, uint8_t *data)
+{
+    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);
+}
+
+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 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("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);
+}
+
+////
+// Perform DMA transactions
+////
+
+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);
+
+    if (ctrl->dmaPending() || ctrl->drainState() != DrainState::Running) {
+        schedule(dmaTransferEvent, curTick() + DMA_BACKOFF_PERIOD);
+        return;
+    } else
+        ctrl->dmaRead(curPrdAddr, sizeof(PrdEntry_t), &dmaPrdReadEvent,
+                (uint8_t*)&curPrd.entry);
+}
+
+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",
+            curPrd.getBaseAddr(), pciToDma(curPrd.getBaseAddr()),
+            curPrd.getByteCount(), (cmdBytesLeft/SectorSize),
+            curPrd.getEOT(), curSector);
+
+    // the prd pointer has already been translated, so just do an increment
+    curPrdAddr = curPrdAddr + sizeof(PrdEntry_t);
+
+    if (dmaRead)
+        doDmaDataRead();
+    else
+        doDmaDataWrite();
+}
+
+void
+IdeDisk::doDmaDataRead()
+{
+    /** @todo we need to figure out what the delay actually will be */
+    Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
+
+    DPRINTF(IdeDisk, "doDmaRead, diskDelay: %d totalDiskDelay: %d\n",
+            diskDelay, totalDiskDelay);
+
+    schedule(dmaReadWaitEvent, curTick() + totalDiskDelay);
+}
+
+void
+IdeDisk::regStats()
+{
+    using namespace Stats;
+    dmaReadFullPages
+        .name(name() + ".dma_read_full_pages")
+        .desc("Number of full page size DMA reads (not PRD).")
+        ;
+    dmaReadBytes
+        .name(name() + ".dma_read_bytes")
+        .desc("Number of bytes transfered via DMA reads (not PRD).")
+        ;
+    dmaReadTxs
+        .name(name() + ".dma_read_txs")
+        .desc("Number of DMA read transactions (not PRD).")
+        ;
+
+    dmaWriteFullPages
+        .name(name() + ".dma_write_full_pages")
+        .desc("Number of full page size DMA writes.")
+        ;
+    dmaWriteBytes
+        .name(name() + ".dma_write_bytes")
+        .desc("Number of bytes transfered via DMA writes.")
+        ;
+    dmaWriteTxs
+        .name(name() + ".dma_write_txs")
+        .desc("Number of DMA write transactions.")
+        ;
+}
+
+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
+        memset(dataBuffer, 0, MAX_DMA_SIZE);
+        dmaReadCG = new ChunkGenerator(curPrd.getBaseAddr(),
+                curPrd.getByteCount(), TheISA::PageBytes);
+
+    }
+    if (ctrl->dmaPending() || ctrl->drainState() != DrainState::Running) {
+        schedule(dmaReadWaitEvent, curTick() + DMA_BACKOFF_PERIOD);
+        return;
+    } else if (!dmaReadCG->done()) {
+        assert(dmaReadCG->complete() < MAX_DMA_SIZE);
+        ctrl->dmaRead(pciToDma(dmaReadCG->addr()), dmaReadCG->size(),
+                &dmaReadWaitEvent, dataBuffer + dmaReadCG->complete());
+        dmaReadBytes += dmaReadCG->size();
+        dmaReadTxs++;
+        if (dmaReadCG->size() == TheISA::PageBytes)
+            dmaReadFullPages++;
+        dmaReadCG->next();
+    } else {
+        assert(dmaReadCG->done());
+        delete dmaReadCG;
+        dmaReadCG = NULL;
+        dmaReadDone();
+    }
+}
+
+void
+IdeDisk::dmaReadDone()
+{
+    uint32_t bytesWritten = 0;
+
+    // write the data to the disk image
+    for (bytesWritten = 0; bytesWritten < curPrd.getByteCount();
+         bytesWritten += SectorSize) {
+
+        cmdBytesLeft -= SectorSize;
+        writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten));
+    }
+
+    // check for the EOT
+    if (curPrd.getEOT()) {
+        assert(cmdBytesLeft == 0);
+        dmaState = Dma_Idle;
+        updateState(ACT_DMA_DONE);
+    } else {
+        doDmaTransfer();
+    }
+}
+
+void
+IdeDisk::doDmaDataWrite()
+{
+    /** @todo we need to figure out what the delay actually will be */
+    Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
+    uint32_t bytesRead = 0;
+
+    DPRINTF(IdeDisk, "doDmaWrite, diskDelay: %d totalDiskDelay: %d\n",
+            diskDelay, totalDiskDelay);
+
+    memset(dataBuffer, 0, MAX_DMA_SIZE);
+    assert(cmdBytesLeft <= MAX_DMA_SIZE);
+    while (bytesRead < curPrd.getByteCount()) {
+        readDisk(curSector++, (uint8_t *)(dataBuffer + bytesRead));
+        bytesRead += SectorSize;
+        cmdBytesLeft -= SectorSize;
+    }
+    DPRINTF(IdeDisk, "doDmaWrite, bytesRead: %d cmdBytesLeft: %d\n",
+            bytesRead, cmdBytesLeft);
+
+    schedule(dmaWriteWaitEvent, curTick() + totalDiskDelay);
+}
+
+void
+IdeDisk::doDmaWrite()
+{
+    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(),
+                curPrd.getByteCount(), TheISA::PageBytes);
+    }
+    if (ctrl->dmaPending() || ctrl->drainState() != DrainState::Running) {
+        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;
+        dmaWriteDone();
+    }
+}
+
+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);
+        dmaState = Dma_Idle;
+        updateState(ACT_DMA_DONE);
+    } else {
+        doDmaTransfer();
+    }
+}
+
+////
+// Disk utility routines
+///
+
+void
+IdeDisk::readDisk(uint32_t sector, uint8_t *data)
+{
+    uint32_t bytesRead = image->read(data, sector);
+
+    if (bytesRead != SectorSize)
+        panic("Can't read from %s. Only %d of %d read. errno=%d\n",
+              name(), bytesRead, SectorSize, errno);
+}
+
+void
+IdeDisk::writeDisk(uint32_t sector, uint8_t *data)
+{
+    uint32_t bytesWritten = image->write(data, sector);
+
+    if (bytesWritten != SectorSize)
+        panic("Can't write to %s. Only %d of %d written. errno=%d\n",
+              name(), bytesWritten, SectorSize, errno);
+}
+
+////
+// Setup and handle commands
+////
+
+void
+IdeDisk::startDma(const uint32_t &prdTableBase)
+{
+    if (dmaState != Dma_Start)
+        panic("Inconsistent DMA state, should be in Dma_Start!\n");
+
+    if (devState != Transfer_Data_Dma)
+        panic("Inconsistent device state for DMA start!\n");
+
+    // PRD base address is given by bits 31:2
+    curPrdAddr = pciToDma((Addr)(prdTableBase & ~ULL(0x3)));
+
+    dmaState = Dma_Transfer;
+
+    // schedule dma transfer (doDmaTransfer)
+    schedule(dmaTransferEvent, curTick() + 1);
+}
+
+void
+IdeDisk::abortDma()
+{
+    if (dmaState == Dma_Idle)
+        panic("Inconsistent DMA state, should be Start or Transfer!");
+
+    if (devState != Transfer_Data_Dma && devState != Prepare_Data_Dma)
+        panic("Inconsistent device state, should be Transfer or Prepare!\n");
+
+    updateState(ACT_CMD_ERROR);
+}
+
+void
+IdeDisk::startCommand()
+{
+    DevAction_t action = ACT_NONE;
+    uint32_t size = 0;
+    dmaRead = false;
+
+    // Decode commands
+    switch (cmdReg.command) {
+        // Supported non-data commands
+      case WDSF_READ_NATIVE_MAX:
+        size = (uint32_t)image->size() - 1;
+        cmdReg.sec_num = (size & 0xff);
+        cmdReg.cyl_low = ((size & 0xff00) >> 8);
+        cmdReg.cyl_high = ((size & 0xff0000) >> 16);
+        cmdReg.head = ((size & 0xf000000) >> 24);
+
+        devState = Command_Execution;
+        action = ACT_CMD_COMPLETE;
+        break;
+
+      case WDCC_RECAL:
+      case WDCC_IDP:
+      case WDCC_STANDBY_IMMED:
+      case WDCC_FLUSHCACHE:
+      case WDSF_VERIFY:
+      case WDSF_SEEK:
+      case SET_FEATURES:
+      case WDCC_SETMULTI:
+      case WDCC_IDLE:
+        devState = Command_Execution;
+        action = ACT_CMD_COMPLETE;
+        break;
+
+        // Supported PIO data-in commands
+      case WDCC_IDENTIFY:
+        cmdBytes = cmdBytesLeft = sizeof(struct ataparams);
+        devState = Prepare_Data_In;
+        action = ACT_DATA_READY;
+        break;
+
+      case WDCC_READMULTI:
+      case WDCC_READ:
+        if (!(cmdReg.drive & DRIVE_LBA_BIT))
+            panic("Attempt to perform CHS access, only supports LBA\n");
+
+        if (cmdReg.sec_count == 0)
+            cmdBytes = cmdBytesLeft = (256 * SectorSize);
+        else
+            cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
+
+        curSector = getLBABase();
+
+        /** @todo make this a scheduled event to simulate disk delay */
+        devState = Prepare_Data_In;
+        action = ACT_DATA_READY;
+        break;
+
+        // Supported PIO data-out commands
+      case WDCC_WRITEMULTI:
+      case WDCC_WRITE:
+        if (!(cmdReg.drive & DRIVE_LBA_BIT))
+            panic("Attempt to perform CHS access, only supports LBA\n");
+
+        if (cmdReg.sec_count == 0)
+            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;
+        action = ACT_DATA_READY;
+        break;
+
+        // Supported DMA commands
+      case WDCC_WRITEDMA:
+        dmaRead = true;  // a write to the disk is a DMA read from memory
+      case WDCC_READDMA:
+        if (!(cmdReg.drive & DRIVE_LBA_BIT))
+            panic("Attempt to perform CHS access, only supports LBA\n");
+
+        if (cmdReg.sec_count == 0)
+            cmdBytes = cmdBytesLeft = (256 * SectorSize);
+        else
+            cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
+        DPRINTF(IdeDisk, "Setting cmdBytesLeft to %d in readdma\n", cmdBytesLeft);
+
+        curSector = getLBABase();
+
+        devState = Prepare_Data_Dma;
+        action = ACT_DMA_READY;
+        break;
+
+      default:
+        panic("Unsupported ATA command: %#x\n", cmdReg.command);
+    }
+
+    if (action != ACT_NONE) {
+        // set the BSY bit
+        status |= STATUS_BSY_BIT;
+        // clear the DRQ bit
+        status &= ~STATUS_DRQ_BIT;
+        // clear the DF bit
+        status &= ~STATUS_DF_BIT;
+
+        updateState(action);
+    }
+}
+
+////
+// Handle setting and clearing interrupts
+////
+
+void
+IdeDisk::intrPost()
+{
+    DPRINTF(IdeDisk, "Posting Interrupt\n");
+    if (intrPending)
+        panic("Attempt to post an interrupt with one pending\n");
+
+    intrPending = true;
+
+    // talk to controller to set interrupt
+    if (ctrl) {
+        ctrl->intrPost();
+    }
+}
+
+void
+IdeDisk::intrClear()
+{
+    DPRINTF(IdeDisk, "Clearing Interrupt\n");
+    if (!intrPending)
+        panic("Attempt to clear a non-pending interrupt\n");
+
+    intrPending = false;
+
+    // talk to controller to clear interrupt
+    if (ctrl)
+        ctrl->intrClear();
+}
+
+////
+// Manage the device internal state machine
+////
+
+void
+IdeDisk::updateState(DevAction_t action)
+{
+    switch (devState) {
+      case Device_Srst:
+        if (action == ACT_SRST_SET) {
+            // set the BSY bit
+            status |= STATUS_BSY_BIT;
+        } else if (action == ACT_SRST_CLEAR) {
+            // clear the BSY bit
+            status &= ~STATUS_BSY_BIT;
+
+            // reset the device state
+            reset(devID);
+        }
+        break;
+
+      case Device_Idle_S:
+        if (action == ACT_SELECT_WRITE && !isDEVSelect()) {
+            devState = Device_Idle_NS;
+        } else if (action == ACT_CMD_WRITE) {
+            startCommand();
+        }
+
+        break;
+
+      case Device_Idle_SI:
+        if (action == ACT_SELECT_WRITE && !isDEVSelect()) {
+            devState = Device_Idle_NS;
+            intrClear();
+        } else if (action == ACT_STAT_READ || isIENSet()) {
+            devState = Device_Idle_S;
+            intrClear();
+        } else if (action == ACT_CMD_WRITE) {
+            intrClear();
+            startCommand();
+        }
+
+        break;
+
+      case Device_Idle_NS:
+        if (action == ACT_SELECT_WRITE && isDEVSelect()) {
+            if (!isIENSet() && intrPending) {
+                devState = Device_Idle_SI;
+                intrPost();
+            }
+            if (isIENSet() || !intrPending) {
+                devState = Device_Idle_S;
+            }
+        }
+        break;
+
+      case Command_Execution:
+        if (action == ACT_CMD_COMPLETE) {
+            // clear the BSY bit
+            setComplete();
+
+            if (!isIENSet()) {
+                devState = Device_Idle_SI;
+                intrPost();
+            } else {
+                devState = Device_Idle_S;
+            }
+        }
+        break;
+
+      case Prepare_Data_In:
+        if (action == ACT_CMD_ERROR) {
+            // clear the BSY bit
+            setComplete();
+
+            if (!isIENSet()) {
+                devState = Device_Idle_SI;
+                intrPost();
+            } else {
+                devState = Device_Idle_S;
+            }
+        } else if (action == ACT_DATA_READY) {
+            // clear the BSY bit
+            status &= ~STATUS_BSY_BIT;
+            // set the DRQ bit
+            status |= STATUS_DRQ_BIT;
+
+            // copy the data into the data buffer
+            if (cmdReg.command == WDCC_IDENTIFY) {
+                // Reset the drqBytes for this block
+                drqBytesLeft = sizeof(struct ataparams);
+
+                memcpy((void *)dataBuffer, (void *)&driveID,
+                       sizeof(struct ataparams));
+            } else {
+                // Reset the drqBytes for this block
+                drqBytesLeft = SectorSize;
+
+                readDisk(curSector++, dataBuffer);
+            }
+
+            // put the first two bytes into the data register
+            memcpy((void *)&cmdReg.data, (void *)dataBuffer,
+                   sizeof(uint16_t));
+
+            if (!isIENSet()) {
+                devState = Data_Ready_INTRQ_In;
+                intrPost();
+            } else {
+                devState = Transfer_Data_In;
+            }
+        }
+        break;
+
+      case Data_Ready_INTRQ_In:
+        if (action == ACT_STAT_READ) {
+            devState = Transfer_Data_In;
+            intrClear();
+        }
+        break;
+
+      case Transfer_Data_In:
+        if (action == ACT_DATA_READ_BYTE || action == ACT_DATA_READ_SHORT) {
+            if (action == ACT_DATA_READ_BYTE) {
+                panic("DEBUG: READING DATA ONE BYTE AT A TIME!\n");
+            } else {
+                drqBytesLeft -= 2;
+                cmdBytesLeft -= 2;
+
+                // copy next short into data registers
+                if (drqBytesLeft)
+                    memcpy((void *)&cmdReg.data,
+                           (void *)&dataBuffer[SectorSize - drqBytesLeft],
+                           sizeof(uint16_t));
+            }
+
+            if (drqBytesLeft == 0) {
+                if (cmdBytesLeft == 0) {
+                    // Clear the BSY bit
+                    setComplete();
+                    devState = Device_Idle_S;
+                } else {
+                    devState = Prepare_Data_In;
+                    // set the BSY_BIT
+                    status |= STATUS_BSY_BIT;
+                    // clear the DRQ_BIT
+                    status &= ~STATUS_DRQ_BIT;
+
+                    /** @todo change this to a scheduled event to simulate
+                        disk delay */
+                    updateState(ACT_DATA_READY);
+                }
+            }
+        }
+        break;
+
+      case Prepare_Data_Out:
+        if (action == ACT_CMD_ERROR || cmdBytesLeft == 0) {
+            // clear the BSY bit
+            setComplete();
+
+            if (!isIENSet()) {
+                devState = Device_Idle_SI;
+                intrPost();
+            } else {
+                devState = Device_Idle_S;
+            }
+        } else if (action == ACT_DATA_READY && cmdBytesLeft != 0) {
+            // clear the BSY bit
+            status &= ~STATUS_BSY_BIT;
+            // set the DRQ bit
+            status |= STATUS_DRQ_BIT;
+
+            // clear the data buffer to get it ready for writes
+            memset(dataBuffer, 0, MAX_DMA_SIZE);
+
+            // reset the drqBytes for this block
+            drqBytesLeft = SectorSize;
+
+            if (cmdBytesLeft == cmdBytes || isIENSet()) {
+                devState = Transfer_Data_Out;
+            } else {
+                devState = Data_Ready_INTRQ_Out;
+                intrPost();
+            }
+        }
+        break;
+
+      case Data_Ready_INTRQ_Out:
+        if (action == ACT_STAT_READ) {
+            devState = Transfer_Data_Out;
+            intrClear();
+        }
+        break;
+
+      case Transfer_Data_Out:
+        if (action == ACT_DATA_WRITE_BYTE ||
+            action == ACT_DATA_WRITE_SHORT) {
+
+            if (action == ACT_DATA_READ_BYTE) {
+                panic("DEBUG: WRITING DATA ONE BYTE AT A TIME!\n");
+            } else {
+                // copy the latest short into the data buffer
+                memcpy((void *)&dataBuffer[SectorSize - drqBytesLeft],
+                       (void *)&cmdReg.data,
+                       sizeof(uint16_t));
+
+                drqBytesLeft -= 2;
+                cmdBytesLeft -= 2;
+            }
+
+            if (drqBytesLeft == 0) {
+                // copy the block to the disk
+                writeDisk(curSector++, dataBuffer);
+
+                // set the BSY bit
+                status |= STATUS_BSY_BIT;
+                // set the seek bit
+                status |= STATUS_SEEK_BIT;
+                // clear the DRQ bit
+                status &= ~STATUS_DRQ_BIT;
+
+                devState = Prepare_Data_Out;
+
+                /** @todo change this to a scheduled event to simulate
+                    disk delay */
+                updateState(ACT_DATA_READY);
+            }
+        }
+        break;
+
+      case Prepare_Data_Dma:
+        if (action == ACT_CMD_ERROR) {
+            // clear the BSY bit
+            setComplete();
+
+            if (!isIENSet()) {
+                devState = Device_Idle_SI;
+                intrPost();
+            } else {
+                devState = Device_Idle_S;
+            }
+        } else if (action == ACT_DMA_READY) {
+            // clear the BSY bit
+            status &= ~STATUS_BSY_BIT;
+            // set the DRQ bit
+            status |= STATUS_DRQ_BIT;
+
+            devState = Transfer_Data_Dma;
+
+            if (dmaState != Dma_Idle)
+                panic("Inconsistent DMA state, should be Dma_Idle\n");
+
+            dmaState = Dma_Start;
+            // wait for the write to the DMA start bit
+        }
+        break;
+
+      case Transfer_Data_Dma:
+        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
+            status |= STATUS_SEEK_BIT;
+            // clear the controller state for DMA transfer
+            ctrl->setDmaComplete(this);
+
+            if (!isIENSet()) {
+                devState = Device_Idle_SI;
+                intrPost();
+            } else {
+                devState = Device_Idle_S;
+            }
+        }
+        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);
+    }
+}
+
+void
+IdeDisk::serialize(CheckpointOut &cp) const
+{
+    // Check all outstanding events to see if they are scheduled
+    // these are all mutually exclusive
+    Tick reschedule = 0;
+    Events_t event = None;
+
+    int eventCount = 0;
+
+    if (dmaTransferEvent.scheduled()) {
+        reschedule = dmaTransferEvent.when();
+        event = Transfer;
+        eventCount++;
+    }
+    if (dmaReadWaitEvent.scheduled()) {
+        reschedule = dmaReadWaitEvent.when();
+        event = ReadWait;
+        eventCount++;
+    }
+    if (dmaWriteWaitEvent.scheduled()) {
+        reschedule = dmaWriteWaitEvent.when();
+        event = WriteWait;
+        eventCount++;
+    }
+    if (dmaPrdReadEvent.scheduled()) {
+        reschedule = dmaPrdReadEvent.when();
+        event = PrdRead;
+        eventCount++;
+    }
+    if (dmaReadEvent.scheduled()) {
+        reschedule = dmaReadEvent.when();
+        event = DmaRead;
+        eventCount++;
+    }
+    if (dmaWriteEvent.scheduled()) {
+        reschedule = dmaWriteEvent.when();
+        event = DmaWrite;
+        eventCount++;
+    }
+
+    assert(eventCount <= 1);
+
+    SERIALIZE_SCALAR(reschedule);
+    SERIALIZE_ENUM(event);
+
+    // Serialize device registers
+    SERIALIZE_SCALAR(cmdReg.data);
+    SERIALIZE_SCALAR(cmdReg.sec_count);
+    SERIALIZE_SCALAR(cmdReg.sec_num);
+    SERIALIZE_SCALAR(cmdReg.cyl_low);
+    SERIALIZE_SCALAR(cmdReg.cyl_high);
+    SERIALIZE_SCALAR(cmdReg.drive);
+    SERIALIZE_SCALAR(cmdReg.command);
+    SERIALIZE_SCALAR(status);
+    SERIALIZE_SCALAR(nIENBit);
+    SERIALIZE_SCALAR(devID);
+
+    // Serialize the PRD related information
+    SERIALIZE_SCALAR(curPrd.entry.baseAddr);
+    SERIALIZE_SCALAR(curPrd.entry.byteCount);
+    SERIALIZE_SCALAR(curPrd.entry.endOfTable);
+    SERIALIZE_SCALAR(curPrdAddr);
+
+    /** @todo need to serialized chunk generator stuff!! */
+    // Serialize current transfer related information
+    SERIALIZE_SCALAR(cmdBytesLeft);
+    SERIALIZE_SCALAR(cmdBytes);
+    SERIALIZE_SCALAR(drqBytesLeft);
+    SERIALIZE_SCALAR(curSector);
+    SERIALIZE_SCALAR(dmaRead);
+    SERIALIZE_SCALAR(intrPending);
+    SERIALIZE_SCALAR(dmaAborted);
+    SERIALIZE_ENUM(devState);
+    SERIALIZE_ENUM(dmaState);
+    SERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);
+}
+
+void
+IdeDisk::unserialize(CheckpointIn &cp)
+{
+    // Reschedule events that were outstanding
+    // these are all mutually exclusive
+    Tick reschedule = 0;
+    Events_t event = None;
+
+    UNSERIALIZE_SCALAR(reschedule);
+    UNSERIALIZE_ENUM(event);
+
+    switch (event) {
+      case None : 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
+    UNSERIALIZE_SCALAR(cmdReg.data);
+    UNSERIALIZE_SCALAR(cmdReg.sec_count);
+    UNSERIALIZE_SCALAR(cmdReg.sec_num);
+    UNSERIALIZE_SCALAR(cmdReg.cyl_low);
+    UNSERIALIZE_SCALAR(cmdReg.cyl_high);
+    UNSERIALIZE_SCALAR(cmdReg.drive);
+    UNSERIALIZE_SCALAR(cmdReg.command);
+    UNSERIALIZE_SCALAR(status);
+    UNSERIALIZE_SCALAR(nIENBit);
+    UNSERIALIZE_SCALAR(devID);
+
+    // Unserialize the PRD related information
+    UNSERIALIZE_SCALAR(curPrd.entry.baseAddr);
+    UNSERIALIZE_SCALAR(curPrd.entry.byteCount);
+    UNSERIALIZE_SCALAR(curPrd.entry.endOfTable);
+    UNSERIALIZE_SCALAR(curPrdAddr);
+
+    /** @todo need to serialized chunk generator stuff!! */
+    // Unserialize current transfer related information
+    UNSERIALIZE_SCALAR(cmdBytes);
+    UNSERIALIZE_SCALAR(cmdBytesLeft);
+    UNSERIALIZE_SCALAR(drqBytesLeft);
+    UNSERIALIZE_SCALAR(curSector);
+    UNSERIALIZE_SCALAR(dmaRead);
+    UNSERIALIZE_SCALAR(intrPending);
+    UNSERIALIZE_SCALAR(dmaAborted);
+    UNSERIALIZE_ENUM(devState);
+    UNSERIALIZE_ENUM(dmaState);
+    UNSERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);
+}
+
+IdeDisk *
+IdeDiskParams::create()
+{
+    return new IdeDisk(this);
+}
diff --git a/src/dev/storage/ide_disk.hh b/src/dev/storage/ide_disk.hh
new file mode 100644 (file)
index 0000000..9214599
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Andrew Schultz
+ */
+
+/** @file
+ * Device model for an IDE disk
+ */
+
+#ifndef __DEV_STORAGE_IDE_DISK_HH__
+#define __DEV_STORAGE_IDE_DISK_HH__
+
+#include "base/statistics.hh"
+#include "dev/io_device.hh"
+#include "dev/storage/disk_image.hh"
+#include "dev/storage/ide_atareg.h"
+#include "dev/storage/ide_ctrl.hh"
+#include "dev/storage/ide_wdcreg.h"
+#include "params/IdeDisk.hh"
+#include "sim/eventq.hh"
+
+class ChunkGenerator;
+
+#define DMA_BACKOFF_PERIOD      200
+
+#define MAX_DMA_SIZE            0x20000  // 128K
+#define MAX_SINGLE_DMA_SIZE     0x10000
+#define MAX_MULTSECT            (128)
+
+#define PRD_BASE_MASK  0xfffffffe
+#define PRD_COUNT_MASK 0xfffe
+#define PRD_EOT_MASK   0x8000
+
+typedef struct PrdEntry {
+    uint32_t baseAddr;
+    uint16_t byteCount;
+    uint16_t endOfTable;
+} PrdEntry_t;
+
+class PrdTableEntry {
+  public:
+    PrdEntry_t entry;
+
+    uint32_t getBaseAddr()
+    {
+        return (entry.baseAddr & PRD_BASE_MASK);
+    }
+
+    uint32_t getByteCount()
+    {
+        return ((entry.byteCount == 0) ? MAX_SINGLE_DMA_SIZE :
+                (entry.byteCount & PRD_COUNT_MASK));
+    }
+
+    uint16_t getEOT()
+    {
+        return (entry.endOfTable & PRD_EOT_MASK);
+    }
+};
+
+#define DATA_OFFSET     (0)
+#define ERROR_OFFSET    (1)
+#define FEATURES_OFFSET (1)
+#define NSECTOR_OFFSET  (2)
+#define SECTOR_OFFSET   (3)
+#define LCYL_OFFSET     (4)
+#define HCYL_OFFSET     (5)
+#define SELECT_OFFSET   (6)
+#define DRIVE_OFFSET    (6)
+#define STATUS_OFFSET   (7)
+#define COMMAND_OFFSET  (7)
+
+#define CONTROL_OFFSET  (2)
+#define ALTSTAT_OFFSET  (2)
+
+#define SELECT_DEV_BIT  0x10
+#define CONTROL_RST_BIT 0x04
+#define CONTROL_IEN_BIT 0x02
+#define STATUS_BSY_BIT  0x80
+#define STATUS_DRDY_BIT 0x40
+#define STATUS_DRQ_BIT  0x08
+#define STATUS_SEEK_BIT 0x10
+#define STATUS_DF_BIT   0x20
+#define DRIVE_LBA_BIT   0x40
+
+#define DEV0 (0)
+#define DEV1 (1)
+
+typedef struct CommandReg {
+    uint16_t data;
+    uint8_t error;
+    uint8_t sec_count;
+    uint8_t sec_num;
+    uint8_t cyl_low;
+    uint8_t cyl_high;
+    union {
+        uint8_t drive;
+        uint8_t head;
+    };
+    uint8_t command;
+} CommandReg_t;
+
+typedef enum Events {
+    None = 0,
+    Transfer,
+    ReadWait,
+    WriteWait,
+    PrdRead,
+    DmaRead,
+    DmaWrite
+} Events_t;
+
+typedef enum DevAction {
+    ACT_NONE = 0,
+    ACT_CMD_WRITE,
+    ACT_CMD_COMPLETE,
+    ACT_CMD_ERROR,
+    ACT_SELECT_WRITE,
+    ACT_STAT_READ,
+    ACT_DATA_READY,
+    ACT_DATA_READ_BYTE,
+    ACT_DATA_READ_SHORT,
+    ACT_DATA_WRITE_BYTE,
+    ACT_DATA_WRITE_SHORT,
+    ACT_DMA_READY,
+    ACT_DMA_DONE,
+    ACT_SRST_SET,
+    ACT_SRST_CLEAR
+} DevAction_t;
+
+typedef enum DevState {
+    // Device idle
+    Device_Idle_S = 0,
+    Device_Idle_SI,
+    Device_Idle_NS,
+
+    // Software reset
+    Device_Srst,
+
+    // Non-data commands
+    Command_Execution,
+
+    // PIO data-in (data to host)
+    Prepare_Data_In,
+    Data_Ready_INTRQ_In,
+    Transfer_Data_In,
+
+    // PIO data-out (data from host)
+    Prepare_Data_Out,
+    Data_Ready_INTRQ_Out,
+    Transfer_Data_Out,
+
+    // DMA protocol
+    Prepare_Data_Dma,
+    Transfer_Data_Dma,
+    Device_Dma_Abort
+} DevState_t;
+
+typedef enum DmaState {
+    Dma_Idle = 0,
+    Dma_Start,
+    Dma_Transfer
+} DmaState_t;
+
+class IdeController;
+
+/**
+ * IDE Disk device model
+ */
+class IdeDisk : public SimObject
+{
+  protected:
+    /** The IDE controller for this disk. */
+    IdeController *ctrl;
+    /** The image that contains the data of this disk. */
+    DiskImage *image;
+
+  protected:
+    /** The disk delay in microseconds. */
+    int diskDelay;
+
+  private:
+    /** Drive identification structure for this disk */
+    struct ataparams driveID;
+    /** Data buffer for transfers */
+    uint8_t *dataBuffer;
+    /** Number of bytes in command data transfer */
+    uint32_t cmdBytes;
+    /** Number of bytes left in command data transfer */
+    uint32_t cmdBytesLeft;
+    /** Number of bytes left in DRQ block */
+    uint32_t drqBytesLeft;
+    /** Current sector in access */
+    uint32_t curSector;
+    /** Command block registers */
+    CommandReg_t cmdReg;
+    /** Status register */
+    uint8_t status;
+    /** Interrupt enable bit */
+    bool nIENBit;
+    /** Device state */
+    DevState_t devState;
+    /** Dma state */
+    DmaState_t dmaState;
+    /** Dma transaction is a read */
+    bool dmaRead;
+    /** PRD table base address */
+    uint32_t curPrdAddr;
+    /** PRD entry */
+    PrdTableEntry curPrd;
+    /** Device ID (master=0/slave=1) */
+    int devID;
+    /** Interrupt pending */
+    bool intrPending;
+    /** DMA Aborted */
+    bool dmaAborted;
+
+    Stats::Scalar dmaReadFullPages;
+    Stats::Scalar dmaReadBytes;
+    Stats::Scalar dmaReadTxs;
+    Stats::Scalar dmaWriteFullPages;
+    Stats::Scalar dmaWriteBytes;
+    Stats::Scalar dmaWriteTxs;
+
+  public:
+    typedef IdeDiskParams Params;
+    IdeDisk(const Params *p);
+
+    /**
+     * Delete the data buffer.
+     */
+    ~IdeDisk();
+
+    /**
+     * Reset the device state
+     */
+    void reset(int id);
+
+    /**
+     * Register Statistics
+     */
+    void regStats() override;
+
+    /**
+     * Set the controller for this device
+     * @param c The IDE controller
+     */
+    void setController(IdeController *c) {
+        if (ctrl) panic("Cannot change the controller once set!\n");
+        ctrl = c;
+    }
+
+    // Device register read/write
+    void readCommand(const Addr offset, int size, uint8_t *data);
+    void readControl(const Addr offset, int size, uint8_t *data);
+    void writeCommand(const Addr offset, int size, const uint8_t *data);
+    void writeControl(const Addr offset, int size, const uint8_t *data);
+
+    // Start/abort functions
+    void startDma(const uint32_t &prdTableBase);
+    void abortDma();
+
+  private:
+    void startCommand();
+
+    // Interrupt management
+    void intrPost();
+    void intrClear();
+
+    // DMA stuff
+    void doDmaTransfer();
+    friend class EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer>;
+    EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer> dmaTransferEvent;
+
+    void doDmaDataRead();
+
+    void doDmaRead();
+    ChunkGenerator *dmaReadCG;
+    friend class EventWrapper<IdeDisk, &IdeDisk::doDmaRead>;
+    EventWrapper<IdeDisk, &IdeDisk::doDmaRead> dmaReadWaitEvent;
+
+    void doDmaDataWrite();
+
+    void doDmaWrite();
+    ChunkGenerator *dmaWriteCG;
+    friend class EventWrapper<IdeDisk, &IdeDisk::doDmaWrite>;
+    EventWrapper<IdeDisk, &IdeDisk::doDmaWrite> dmaWriteWaitEvent;
+
+    void dmaPrdReadDone();
+    friend class EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone>;
+    EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone> dmaPrdReadEvent;
+
+    void dmaReadDone();
+    friend class EventWrapper<IdeDisk, &IdeDisk::dmaReadDone>;
+    EventWrapper<IdeDisk, &IdeDisk::dmaReadDone> dmaReadEvent;
+
+    void dmaWriteDone();
+    friend class EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone>;
+    EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone> dmaWriteEvent;
+
+    // Disk image read/write
+    void readDisk(uint32_t sector, uint8_t *data);
+    void writeDisk(uint32_t sector, uint8_t *data);
+
+    // State machine management
+    void updateState(DevAction_t action);
+
+    // Utility functions
+    bool isBSYSet() { return (status & STATUS_BSY_BIT); }
+    bool isIENSet() { return nIENBit; }
+    bool isDEVSelect();
+
+    void setComplete()
+    {
+        // clear out the status byte
+        status = 0;
+        // set the DRDY bit
+        status |= STATUS_DRDY_BIT;
+        // set the SEEK bit
+        status |= STATUS_SEEK_BIT;
+    }
+
+    uint32_t getLBABase()
+    {
+        return  (Addr)(((cmdReg.head & 0xf) << 24) | (cmdReg.cyl_high << 16) |
+                       (cmdReg.cyl_low << 8) | (cmdReg.sec_num));
+    }
+
+    inline Addr pciToDma(Addr pciAddr);
+
+    void serialize(CheckpointOut &cp) const override;
+    void unserialize(CheckpointIn &cp) override;
+};
+
+
+#endif // __DEV_STORAGE_IDE_DISK_HH__
diff --git a/src/dev/storage/ide_wdcreg.h b/src/dev/storage/ide_wdcreg.h
new file mode 100644 (file)
index 0000000..f6a59c9
--- /dev/null
@@ -0,0 +1,197 @@
+/*      $OpenBSD: wdcreg.h,v 1.13 2004/09/24 07:05:44 grange Exp $     */
+/*     $NetBSD: wdcreg.h,v 1.22 1999/03/07 14:02:54 bouyer Exp $       */
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California
+ * All rights reserved
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)wdreg.h     7.1 (Berkeley) 5/9/91
+ */
+
+#ifndef _DEV_IC_WDCREG_H_
+#define _DEV_IC_WDCREG_H_
+
+/*
+ * Controller register (wdr_ctlr)
+ */
+#define WDCTL_4BIT     0x08    /* use four head bits (wd1003) */
+#define WDCTL_RST      0x04    /* reset the controller */
+#define WDCTL_IDS      0x02    /* disable controller interrupts */
+
+/*
+ * Status bits.
+ */
+#define WDCS_BSY       0x80    /* busy */
+#define WDCS_DRDY      0x40    /* drive ready */
+#define WDCS_DWF       0x20    /* drive write fault */
+#define WDCS_DSC       0x10    /* drive seek complete */
+#define WDCS_DRQ       0x08    /* data request */
+#define WDCS_CORR      0x04    /* corrected data */
+#define WDCS_IDX       0x02    /* index */
+#define WDCS_ERR       0x01    /* error */
+#define WDCS_BITS      "\020\010BSY\007DRDY\006DWF\005DSC\004DRQ\003CORR\002IDX\001ERR"
+
+/*
+ * Error bits.
+ */
+#define WDCE_BBK       0x80    /* bad block detected */
+#define WDCE_CRC       0x80    /* CRC error (Ultra-DMA only) */
+#define WDCE_UNC       0x40    /* uncorrectable data error */
+#define WDCE_MC                0x20    /* media changed */
+#define WDCE_IDNF      0x10    /* id not found */
+#define WDCE_MCR       0x08    /* media change requested */
+#define WDCE_ABRT      0x04    /* aborted command */
+#define WDCE_TK0NF     0x02    /* track 0 not found */
+#define WDCE_AMNF      0x01    /* address mark not found */
+
+/*
+ * Commands for Disk Controller.
+ */
+#define WDCC_NOP       0x00    /* NOP - Always fail with "aborted command" */
+#define WDCC_RECAL     0x10    /* disk restore code -- resets cntlr */
+
+#define WDCC_READ      0x20    /* disk read code */
+#define WDCC_WRITE     0x30    /* disk write code */
+#define WDCC__LONG     0x02    /* modifier -- access ecc bytes */
+#define WDCC__NORETRY  0x01    /* modifier -- no retrys */
+
+#define WDCC_FORMAT    0x50    /* disk format code */
+#define WDCC_DIAGNOSE  0x90    /* controller diagnostic */
+#define WDCC_IDP       0x91    /* initialize drive parameters */
+
+#define WDCC_READMULTI 0xc4    /* read multiple */
+#define WDCC_WRITEMULTI        0xc5    /* write multiple */
+#define WDCC_SETMULTI  0xc6    /* set multiple mode */
+
+#define WDCC_READDMA   0xc8    /* read with DMA */
+#define WDCC_WRITEDMA  0xca    /* write with DMA */
+
+#define WDCC_ACKMC     0xdb    /* acknowledge media change */
+#define WDCC_LOCK      0xde    /* lock drawer */
+#define WDCC_UNLOCK    0xdf    /* unlock drawer */
+
+#define WDCC_FLUSHCACHE        0xe7    /* Flush cache */
+#define WDCC_IDENTIFY  0xec    /* read parameters from controller */
+#define SET_FEATURES   0xef    /* set features */
+
+#define WDCC_IDLE      0xe3    /* set idle timer & enter idle mode */
+#define WDCC_IDLE_IMMED        0xe1    /* enter idle mode */
+#define WDCC_SLEEP     0xe6    /* enter sleep mode */
+#define WDCC_STANDBY   0xe2    /* set standby timer & enter standby mode */
+#define WDCC_STANDBY_IMMED 0xe0        /* enter standby mode */
+#define WDCC_CHECK_PWR 0xe5    /* check power mode */
+
+#define WDCC_READ_EXT          0x24 /* read 48-bit addressing */
+#define WDCC_WRITE_EXT         0x34 /* write 48-bit addressing */
+
+#define WDCC_READMULTI_EXT     0x29 /* read multiple 48-bit addressing */
+#define WDCC_WRITEMULTI_EXT    0x39 /* write multiple 48-bit addressing */
+
+#define WDCC_READDMA_EXT       0x25 /* read 48-bit addressing with DMA */
+#define WDCC_WRITEDMA_EXT      0x35 /* write 48-bit addressing with DMA */
+
+#define WDCC_FLUSHCACHE_EXT    0xea /* 48-bit addressing flush cache */
+
+/* Subcommands for SET_FEATURES (features register ) */
+#define WDSF_8BIT_PIO_EN       0x01 /* Enable 8bit PIO (CFA featureset) */
+#define WDSF_EN_WR_CACHE       0x02
+#define WDSF_SET_MODE          0x03
+#define WDSF_REASSIGN_EN       0x04 /* Obsolete in ATA-6 */
+#define WDSF_APM_EN            0x05 /* Enable Adv. Power Management */
+#define WDSF_PUIS_EN           0x06 /* Enable Power-Up In Standby */
+#define WDSF_PUIS_SPINUP       0x07 /* Power-Up In Standby spin-up */
+#define WDSF_CFA_MODE1_EN      0x0A /* Enable CFA power mode 1 */
+#define WDSF_RMSN_DS           0x31 /* Disable Removable Media Status */
+#define WDSF_RETRY_DS          0x33 /* Obsolete in ATA-6 */
+#define WDSF_AAM_EN            0x42 /* Enable Autom. Acoustic Management */
+#define WDSF_SET_CACHE_SGMT    0x54 /* Obsolete in ATA-6 */
+#define WDSF_READAHEAD_DS      0x55 /* Disable read look-ahead */
+#define WDSF_RLSE_EN           0x5D /* Enable release interrupt */
+#define WDSF_SRV_EN            0x5E /* Enable SERVICE interrupt */
+#define WDSF_POD_DS            0x66
+#define WDSF_ECC_DS            0x77
+#define WDSF_8BIT_PIO_DS       0x81 /* Disable 8bit PIO (CFA featureset) */
+#define WDSF_WRITE_CACHE_DS    0x82
+#define WDSF_REASSIGN_DS       0x84
+#define WDSF_APM_DS            0x85 /* Disable Adv. Power Management */
+#define WDSF_PUIS_DS           0x86 /* Disable Power-Up In Standby */
+#define WDSF_ECC_EN            0x88
+#define WDSF_CFA_MODE1_DS      0x8A /* Disable CFA power mode 1 */
+#define WDSF_RMSN_EN           0x95 /* Enable Removable Media Status */
+#define WDSF_RETRY_EN          0x99 /* Obsolete in ATA-6 */
+#define WDSF_SET_CURRENT       0x9A /* Obsolete in ATA-6 */
+#define WDSF_READAHEAD_EN      0xAA
+#define WDSF_PREFETCH_SET      0xAB /* Obsolete in ATA-6 */
+#define WDSF_AAM_DS            0xC2 /* Disable Autom. Acoustic Management */
+#define WDSF_POD_EN            0xCC
+#define WDSF_RLSE_DS           0xDD /* Disable release interrupt */
+#define WDSF_SRV_DS            0xDE /* Disable SERVICE interrupt */
+#define WDSF_READ_NATIVE_MAX    0xF8
+#define WDSF_SEEK               0x70
+#define WDSF_VERIFY             0x40
+
+/* parameters uploaded to device/heads register */
+#define WDSD_IBM       0xa0    /* forced to 512 byte sector, ecc */
+#define WDSD_CHS       0x00    /* cylinder/head/sector addressing */
+#define WDSD_LBA       0x40    /* logical block addressing */
+
+/* Commands for ATAPI devices */
+#define ATAPI_CHECK_POWER_MODE 0xe5
+#define ATAPI_EXEC_DRIVE_DIAGS 0x90
+#define ATAPI_IDLE_IMMEDIATE   0xe1
+#define ATAPI_NOP              0x00
+#define ATAPI_PKT_CMD          0xa0
+#define ATAPI_IDENTIFY_DEVICE  0xa1
+#define ATAPI_SOFT_RESET       0x08
+#define ATAPI_DEVICE_RESET     0x08 /* ATA/ATAPI-5 name for soft reset */
+#define ATAPI_SLEEP            0xe6
+#define ATAPI_STANDBY_IMMEDIATE        0xe0
+#define ATAPI_SMART            0xB0 /* SMART operations */
+#define ATAPI_SETMAX           0xF9 /* Set Max Address */
+#define ATAPI_WRITEEXT         0x34 /* Write sectors Ext */
+#define ATAPI_SETMAXEXT                0x37 /* Set Max Address Ext */
+#define ATAPI_WRITEMULTIEXT    0x39 /* Write Multi Ext */
+
+/* Bytes used by ATAPI_PACKET_COMMAND ( feature register) */
+#define ATAPI_PKT_CMD_FTRE_DMA 0x01
+#define ATAPI_PKT_CMD_FTRE_OVL 0x02
+
+/* ireason */
+#define WDCI_CMD       0x01 /* command(1) or data(0) */
+#define WDCI_IN                0x02 /* transfer to(1) or from(0) the host */
+#define WDCI_RELEASE   0x04 /* bus released until completion */
+
+#define PHASE_CMDOUT   (WDCS_DRQ | WDCI_CMD)
+#define PHASE_DATAIN   (WDCS_DRQ | WDCI_IN)
+#define PHASE_DATAOUT  WDCS_DRQ
+#define PHASE_COMPLETED        (WDCI_IN | WDCI_CMD)
+#define PHASE_ABORTED  0
+
+#endif /* !_DEV_IC_WDCREG_H_ */
diff --git a/src/dev/storage/simple_disk.cc b/src/dev/storage/simple_disk.cc
new file mode 100644 (file)
index 0000000..49c001a
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+/* @file
+ * Simple disk interface for the system console
+ */
+
+#include "dev/storage/simple_disk.hh"
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#include <cstring>
+#include <string>
+
+#include "base/misc.hh"
+#include "base/trace.hh"
+#include "debug/SimpleDisk.hh"
+#include "debug/SimpleDiskData.hh"
+#include "dev/storage/disk_image.hh"
+#include "mem/port_proxy.hh"
+#include "sim/system.hh"
+
+using namespace std;
+
+SimpleDisk::SimpleDisk(const Params *p)
+    : SimObject(p), system(p->system), image(p->disk)
+{}
+
+SimpleDisk::~SimpleDisk()
+{}
+
+
+void
+SimpleDisk::read(Addr addr, baddr_t block, int count) const
+{
+    uint8_t *data = new uint8_t[SectorSize * count];
+
+    if (count & (SectorSize - 1))
+        panic("Not reading a multiple of a sector (count = %d)", count);
+
+    for (int i = 0, j = 0; i < count; i += SectorSize, j++)
+        image->read(data + i, block + j);
+
+    system->physProxy.writeBlob(addr, data, count);
+
+    DPRINTF(SimpleDisk, "read  block=%#x len=%d\n", (uint64_t)block, count);
+    DDUMP(SimpleDiskData, data, count);
+
+    delete [] data;
+}
+
+void
+SimpleDisk::write(Addr addr, baddr_t block, int count)
+{
+    panic("unimplemented!\n");
+
+#if 0
+    uint8_t *data = physmem->dma_addr(addr, count);
+    if (!data)
+        panic("dma out of range! write addr=%#x count=%d\n", addr, count);
+
+    image->write(data, block, count);
+#endif
+}
+
+SimpleDisk *
+SimpleDiskParams::create()
+{
+    return new SimpleDisk(this);
+}
diff --git a/src/dev/storage/simple_disk.hh b/src/dev/storage/simple_disk.hh
new file mode 100644 (file)
index 0000000..2a3ff49
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+/* @file
+ * Simple disk interface for the system console
+ */
+
+#ifndef __DEV_STORAGE_SIMPLE_DISK_HH__
+#define __DEV_STORAGE_SIMPLE_DISK_HH__
+
+#include "params/SimpleDisk.hh"
+#include "sim/sim_object.hh"
+
+class DiskImage;
+class System;
+
+/*
+ * Trivial interface to a disk image used by the System Console
+ */
+class SimpleDisk : public SimObject
+{
+  public:
+    typedef uint64_t baddr_t;
+
+  protected:
+    System  *system;
+    DiskImage *image;
+
+  public:
+    typedef SimpleDiskParams Params;
+    SimpleDisk(const Params *p);
+    ~SimpleDisk();
+
+    void read(Addr addr, baddr_t block, int count) const;
+    void write(Addr addr, baddr_t block, int count);
+};
+
+#endif // __DEV_STORAGE_SIMPLE_DISK_HH__
index bef29580bcfaea9c94c4cf00bf35d96e06e52921..fbbb5185458f54b5d27b12162d7f1f74c62bad8c 100644 (file)
@@ -41,7 +41,7 @@
 #define __DEV_VIRTIO_BLOCK_HH__
 
 #include "dev/virtio/base.hh"
-#include "dev/disk_image.hh"
+#include "dev/storage/disk_image.hh"
 #include "dev/terminal.hh"
 
 struct VirtIOBlockParams;