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

#include "dev/storage/ide_ctrl.hh"

#include <string>

#include "base/cprintf.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"

namespace gem5
{

// Bus master IDE registers
enum BMIRegOffset
{
    BMICommand = 0x0,
    BMIStatus = 0x2,
    BMIDescTablePtr = 0x4
};

IdeController::Channel::Channel(std::string newName) : _name(newName)
{
    bmiRegs.reset();
    bmiRegs.status.dmaCap0 = 1;
    bmiRegs.status.dmaCap1 = 1;
}

IdeController::IdeController(const Params &p)
    : PciDevice(p), configSpaceRegs(name() + ".config_space_regs"),
    primary(name() + ".primary"),
    secondary(name() + ".secondary"),
    ioShift(p.io_shift), ctrlOffset(p.ctrl_offset)
{

    // Assign the disks to channels
    for (int i = 0; i < params().disks.size(); i++) {
        if (!params().disks[i])
            continue;
        switch (i) {
          case 0:
            primary.device0 = params().disks[0];
            break;
          case 1:
            primary.device1 = params().disks[1];
            break;
          case 2:
            secondary.device0 = params().disks[2];
            break;
          case 3:
            secondary.device1 = params().disks[3];
            break;
          default:
            panic("IDE controllers support a maximum "
                  "of 4 devices attached!\n");
        }
        // Arbitrarily set the chunk size to 4K.
        params().disks[i]->setController(this, 4 * 1024);
    }

    primary.select(false);
    secondary.select(false);
}

void
IdeController::ConfigSpaceRegs::serialize(CheckpointOut &cp) const
{
    SERIALIZE_SCALAR(primaryTiming);
    SERIALIZE_SCALAR(secondaryTiming);
    SERIALIZE_SCALAR(deviceTiming);
    SERIALIZE_SCALAR(udmaControl);
    SERIALIZE_SCALAR(udmaTiming);
}

void
IdeController::ConfigSpaceRegs::unserialize(CheckpointIn &cp)
{
    UNSERIALIZE_SCALAR(primaryTiming);
    UNSERIALIZE_SCALAR(secondaryTiming);
    UNSERIALIZE_SCALAR(deviceTiming);
    UNSERIALIZE_SCALAR(udmaControl);
    UNSERIALIZE_SCALAR(udmaTiming);
}

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.device0 || disk == primary.device1) {
        channel = &primary;
    } else if (disk == secondary.device0 || disk == secondary.device1) {
        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);

    size_t size = pkt->getSize();

    configSpaceRegs.read(offset, pkt->getPtr<void>(), size);

    DPRINTF(IdeCtrl, "PCI read offset: %#x size: %d data: %#x\n", offset, size,
            pkt->getUintX(ByteOrder::little));

    pkt->makeAtomicResponse();
    return configDelay;
}


Tick
IdeController::writeConfig(PacketPtr pkt)
{
    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;

    if (offset < PCI_DEVICE_SPECIFIC)
        return PciDevice::writeConfig(pkt);

    size_t size = pkt->getSize();

    DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n",
            offset, size, pkt->getUintX(ByteOrder::little));

    configSpaceRegs.write(offset, pkt->getConstPtr<void>(), size);

    pkt->makeAtomicResponse();
    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 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());

    Addr addr = pkt->getAddr();
    int size = pkt->getSize();
    uint8_t *dataPtr = pkt->getPtr<uint8_t>();

    int bar_num;
    Addr offset;
    panic_if(!getBAR(addr, bar_num, offset),
        "IDE controller access to invalid address: %#x.", addr);

    switch (bar_num) {
      case 0:
        // linux may have shifted the address by ioShift,
        // here we shift it back, similarly for ctrlOffset.
        offset >>= ioShift;
        primary.accessCommand(offset, size, dataPtr, read);
        break;
      case 1:
        offset += ctrlOffset;
        primary.accessControl(offset, size, dataPtr, read);
        break;
      case 2:
        secondary.accessCommand(offset, size, dataPtr, read);
        break;
      case 3:
        secondary.accessControl(offset, size, dataPtr, read);
        break;
      case 4:
        {
            PciCommandRegister command = letoh(config.command);
            if (!read && !command.busMaster)
                return;

            if (offset < sizeof(Channel::BMIRegs)) {
                primary.accessBMI(offset, size, dataPtr, read);
            } else {
                offset -= sizeof(Channel::BMIRegs);
                secondary.accessBMI(offset, size, dataPtr, read);
            }
        }
    }

#ifndef NDEBUG
    uint32_t data;
    if (pkt->getSize() == 1)
        data = pkt->getLE<uint8_t>();
    else if (pkt->getSize() == 2)
        data = pkt->getLE<uint16_t>();
    else
        data = pkt->getLE<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
    configSpaceRegs.serialize(cp);
}

void
IdeController::Channel::serialize(const std::string &base,
                                  CheckpointOut &cp) const
{
    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
    configSpaceRegs.unserialize(cp);
}

void
IdeController::Channel::unserialize(const std::string &base, CheckpointIn &cp)
{
    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);
}

} // namespace gem5
