/*
 * 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.
 */

/** @file
 * This device acts as a disk similar to the memory mapped disk device
 * in legion. Any access is translated to an offset in the disk image.
 */

#include "dev/sparc/mm_disk.hh"

#include <cstring>

#include "base/trace.hh"
#include "debug/IdeDisk.hh"
#include "dev/platform.hh"
#include "mem/packet_access.hh"
#include "mem/port.hh"
#include "sim/byteswap.hh"
#include "sim/system.hh"

MmDisk::MmDisk(const Params *p)
    : BasicPioDevice(p, p->image->size() * SectorSize),
      image(p->image), curSector((off_t)-1), dirty(false)
{
    std::memset(&diskData, 0, SectorSize);
}

Tick
MmDisk::read(PacketPtr pkt)
{
    Addr accessAddr;
    off_t sector;
    uint16_t d16;
    uint32_t d32;
    uint64_t d64;

    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
    accessAddr = pkt->getAddr() - pioAddr;

    sector = accessAddr / SectorSize;

    if (sector != curSector) {
        if (dirty) {
#ifndef NDEBUG
            off_t bytes_written =
#endif
                image->write(diskData, curSector);
            assert(bytes_written == SectorSize);
        }
#ifndef NDEBUG
        off_t bytes_read =
#endif
            image->read(diskData, sector);
        assert(bytes_read == SectorSize);
        curSector = sector;
    }
    switch (pkt->getSize()) {
      case sizeof(uint8_t):
        pkt->setRaw(diskData[accessAddr % SectorSize]);
        DPRINTF(IdeDisk, "reading byte %#x value= %#x\n",
                accessAddr, diskData[accessAddr % SectorSize]);
        break;
      case sizeof(uint16_t):
        memcpy(&d16, diskData + (accessAddr % SectorSize), 2);
        pkt->setRaw(d16);
        DPRINTF(IdeDisk, "reading word %#x value= %#x\n", accessAddr, d16);
        break;
      case sizeof(uint32_t):
        memcpy(&d32, diskData + (accessAddr % SectorSize), 4);
        pkt->setRaw(d32);
        DPRINTF(IdeDisk, "reading dword %#x value= %#x\n", accessAddr, d32);
        break;
      case sizeof(uint64_t):
        memcpy(&d64, diskData + (accessAddr % SectorSize), 8);
        pkt->setRaw(d64);
        DPRINTF(IdeDisk, "reading qword %#x value= %#x\n", accessAddr, d64);
        break;
      default:
        panic("Invalid access size\n");
    }

    pkt->makeAtomicResponse();
    return pioDelay;
}

Tick
MmDisk::write(PacketPtr pkt)
{
    Addr accessAddr;
    off_t sector;
    uint16_t d16;
    uint32_t d32;
    uint64_t d64;

    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
    accessAddr = pkt->getAddr() - pioAddr;

    sector = accessAddr / SectorSize;

    if (sector != curSector) {
        if (dirty) {
#ifndef NDEBUG
            off_t bytes_written =
#endif
                image->write(diskData, curSector);
            assert(bytes_written == SectorSize);
        }
#ifndef NDEBUG
        off_t bytes_read =
#endif
            image->read(diskData,  sector);
        assert(bytes_read == SectorSize);
        curSector = sector;
    }
    dirty = true;

    switch (pkt->getSize()) {
      case sizeof(uint8_t):
        diskData[accessAddr % SectorSize] = htobe(pkt->getRaw<uint8_t>());
        DPRINTF(IdeDisk, "writing byte %#x value= %#x\n",
                accessAddr, diskData[accessAddr % SectorSize]);
        break;
      case sizeof(uint16_t):
        d16 = pkt->getRaw<uint16_t>();
        memcpy(diskData + (accessAddr % SectorSize), &d16, 2);
        DPRINTF(IdeDisk, "writing word %#x value= %#x\n", accessAddr, d16);
        break;
      case sizeof(uint32_t):
        d32 = pkt->getRaw<uint32_t>();
        memcpy(diskData + (accessAddr % SectorSize), &d32, 4);
        DPRINTF(IdeDisk, "writing dword %#x value= %#x\n", accessAddr, d32);
        break;
      case sizeof(uint64_t):
        d64 = pkt->getRaw<uint64_t>();
        memcpy(diskData + (accessAddr % SectorSize), &d64, 8);
        DPRINTF(IdeDisk, "writing qword %#x value= %#x\n", accessAddr, d64);
        break;
      default:
        panic("Invalid access size\n");
    }

    pkt->makeAtomicResponse();
    return pioDelay;
}

void
MmDisk::serialize(CheckpointOut &cp) const
{
    // just write any dirty changes to the cow layer it will take care of
    // serialization
    if (dirty) {
#ifndef NDEBUG
        int bytes_read =
#endif
            image->write(diskData, curSector);
        assert(bytes_read == SectorSize);
    }
    ClockedObject::serialize(cp);
}

MmDisk *
MmDiskParams::create()
{
    return new MmDisk(this);
}
