/*
 * 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 implemetns the niagara I/O bridge chip. It manages incomming
 * interrupts and posts them to the CPU when needed. It holds mask registers and
 * various status registers for CPUs to check what interrupts are pending as
 * well as facilities to send IPIs to other cpus.
 */

#include "dev/sparc/iob.hh"

#include <cstring>

#include "arch/sparc/faults.hh"
#include "arch/sparc/interrupts.hh"
#include "arch/sparc/isa_traits.hh"
#include "base/bitfield.hh"
#include "base/trace.hh"
#include "cpu/intr_control.hh"
#include "cpu/thread_context.hh"
#include "debug/Iob.hh"
#include "dev/platform.hh"
#include "mem/packet_access.hh"
#include "mem/port.hh"
#include "sim/faults.hh"
#include "sim/system.hh"

Iob::Iob(const Params &p)
    : PioDevice(p), ic(p.platform->intrctrl)
{
    iobManAddr = ULL(0x9800000000);
    iobManSize = ULL(0x0100000000);
    iobJBusAddr = ULL(0x9F00000000);
    iobJBusSize = ULL(0x0100000000);
    assert(params().system->threads.size() <= MaxNiagaraProcs);

    pioDelay = p.pio_latency;

    for (int x = 0; x < NumDeviceIds; ++x) {
        intMan[x].cpu = 0;
        intMan[x].vector = 0;
        intCtl[x].mask = true;
        intCtl[x].pend = false;
    }

}

Tick
Iob::read(PacketPtr pkt)
{

    if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
        readIob(pkt);
    else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
        readJBus(pkt);
    else
        panic("Invalid address reached Iob\n");

    pkt->makeAtomicResponse();
    return pioDelay;
}

void
Iob::readIob(PacketPtr pkt)
{
        Addr accessAddr = pkt->getAddr() - iobManAddr;

        assert(IntManAddr == 0);
        if (accessAddr < IntManAddr + IntManSize) {
            int index = (accessAddr - IntManAddr) >> 3;
            uint64_t data = intMan[index].cpu << 8 | intMan[index].vector << 0;
            pkt->setBE(data);
            return;
        }

        if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
            int index = (accessAddr - IntCtlAddr) >> 3;
            uint64_t data = intCtl[index].mask  ? 1 << 2 : 0 |
                intCtl[index].pend  ? 1 << 0 : 0;
            pkt->setBE(data);
            return;
        }

        if (accessAddr == JIntVecAddr) {
            pkt->setBE(jIntVec);
            return;
        }

        panic("Read to unknown IOB offset 0x%x\n", accessAddr);
}

void
Iob::readJBus(PacketPtr pkt)
{
        Addr accessAddr = pkt->getAddr() - iobJBusAddr;
        ContextID cpuid = pkt->req->contextId();
        int index;
        uint64_t data;




        if (accessAddr >= JIntData0Addr && accessAddr < JIntData1Addr) {
            index = (accessAddr - JIntData0Addr) >> 3;
            pkt->setBE(jBusData0[index]);
            return;
        }

        if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) {
            index = (accessAddr - JIntData1Addr) >> 3;
            pkt->setBE(jBusData1[index]);
            return;
        }

        if (accessAddr == JIntDataA0Addr) {
            pkt->setBE(jBusData0[cpuid]);
            return;
        }

        if (accessAddr == JIntDataA1Addr) {
            pkt->setBE(jBusData1[cpuid]);
            return;
        }

        if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
            index = (accessAddr - JIntBusyAddr) >> 3;
            data = jIntBusy[index].busy ? 1 << 5 : 0 |
                   jIntBusy[index].source;
            pkt->setBE(data);
            return;
        }
        if (accessAddr == JIntABusyAddr) {
            data = jIntBusy[cpuid].busy ? 1 << 5 : 0 |
                   jIntBusy[cpuid].source;
            pkt->setBE(data);
            return;
        };

        panic("Read to unknown JBus offset 0x%x\n", accessAddr);
}

Tick
Iob::write(PacketPtr pkt)
{
    if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
        writeIob(pkt);
    else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
        writeJBus(pkt);
    else
        panic("Invalid address reached Iob\n");


    pkt->makeAtomicResponse();
    return pioDelay;
}

void
Iob::writeIob(PacketPtr pkt)
{
        Addr accessAddr = pkt->getAddr() - iobManAddr;
        int index;
        uint64_t data;

        assert(IntManAddr == 0);
        if (accessAddr < IntManAddr + IntManSize) {
            index = (accessAddr - IntManAddr) >> 3;
            data = pkt->getBE<uint64_t>();
            intMan[index].cpu = bits(data,12,8);
            intMan[index].vector = bits(data,5,0);
            DPRINTF(Iob, "Wrote IntMan %d cpu %d, vec %d\n", index,
                    intMan[index].cpu, intMan[index].vector);
            return;
        }

        if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
            index = (accessAddr - IntCtlAddr) >> 3;
            data = pkt->getBE<uint64_t>();
            intCtl[index].mask = bits(data,2,2);
            if (bits(data,1,1))
                intCtl[index].pend = false;
            DPRINTF(Iob, "Wrote IntCtl %d pend %d cleared %d\n", index,
                    intCtl[index].pend, bits(data,2,2));
            return;
        }

        if (accessAddr == JIntVecAddr) {
            jIntVec = bits(pkt->getBE<uint64_t>(), 5,0);
            DPRINTF(Iob, "Wrote jIntVec %d\n", jIntVec);
            return;
        }

        if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) {
            Type type;
            int cpu_id;
            int vector;
            index = (accessAddr - IntManAddr) >> 3;
            data = pkt->getBE<uint64_t>();
            type = (Type)bits(data,17,16);
            cpu_id = bits(data, 12,8);
            vector = bits(data,5,0);
            generateIpi(type,cpu_id, vector);
            return;
        }

        panic("Write to unknown IOB offset 0x%x\n", accessAddr);
}

void
Iob::writeJBus(PacketPtr pkt)
{
        Addr accessAddr = pkt->getAddr() - iobJBusAddr;
        ContextID cpuid = pkt->req->contextId();
        int index;
        uint64_t data;

        if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
            index = (accessAddr - JIntBusyAddr) >> 3;
            data = pkt->getBE<uint64_t>();
            jIntBusy[index].busy = bits(data,5,5);
            DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", index,
                    jIntBusy[index].busy);
            return;
        }
        if (accessAddr == JIntABusyAddr) {
            data = pkt->getBE<uint64_t>();
            jIntBusy[cpuid].busy = bits(data,5,5);
            DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", cpuid,
                    jIntBusy[cpuid].busy);
            return;
        };

        panic("Write to unknown JBus offset 0x%x\n", accessAddr);
}

void
Iob::receiveDeviceInterrupt(DeviceId devid)
{
    assert(devid < NumDeviceIds);
    if (intCtl[devid].mask)
        return;
    intCtl[devid].mask = true;
    intCtl[devid].pend = true;
    DPRINTF(Iob, "Receiving Device interrupt: %d for cpu %d vec %d\n",
            devid, intMan[devid].cpu, intMan[devid].vector);
    ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector);
}


void
Iob::generateIpi(Type type, int cpu_id, int vector)
{
    SparcISA::SparcFault<SparcISA::PowerOnReset> *por = new SparcISA::PowerOnReset();
    if (cpu_id >= sys->threads.size())
        return;

    switch (type) {
      case 0: // interrupt
        DPRINTF(Iob, "Generating interrupt because of I/O write to cpu: %d vec %d\n",
                cpu_id, vector);
        ic->post(cpu_id, SparcISA::IT_INT_VEC, vector);
        break;
      case 1: // reset
        warn("Sending reset to CPU: %d\n", cpu_id);
        if (vector != por->trapType())
            panic("Don't know how to set non-POR reset to cpu\n");
        por->invoke(sys->threads[cpu_id]);
        sys->threads[cpu_id]->activate();
        break;
      case 2: // idle -- this means stop executing and don't wake on interrupts
        DPRINTF(Iob, "Idling CPU because of I/O write cpu: %d\n", cpu_id);
        sys->threads[cpu_id]->halt();
        break;
      case 3: // resume
        DPRINTF(Iob, "Resuming CPU because of I/O write cpu: %d\n", cpu_id);
        sys->threads[cpu_id]->activate();
        break;
      default:
        panic("Invalid type to generate ipi\n");
    }
}

bool
Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
{
    // If we are already dealing with an interrupt for that cpu we can't deal
    // with another one right now... come back later
    if (jIntBusy[cpu_id].busy)
        return false;

    DPRINTF(Iob, "Receiving jBus interrupt: %d for cpu %d vec %d\n",
            source, cpu_id, jIntVec);

    jIntBusy[cpu_id].busy = true;
    jIntBusy[cpu_id].source = source;
    jBusData0[cpu_id] = d0;
    jBusData1[cpu_id] = d1;

    ic->post(cpu_id, SparcISA::IT_INT_VEC, jIntVec);
    return true;
}

AddrRangeList
Iob::getAddrRanges() const
{
    AddrRangeList ranges;
    ranges.push_back(RangeSize(iobManAddr, iobManSize));
    ranges.push_back(RangeSize(iobJBusAddr, iobJBusSize));
    return ranges;
}


void
Iob::serialize(CheckpointOut &cp) const
{

    SERIALIZE_SCALAR(jIntVec);
    SERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
    SERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
    for (int x = 0; x < NumDeviceIds; x++) {
        ScopedCheckpointSection sec(cp, csprintf("Int%d", x));
        paramOut(cp, "cpu", intMan[x].cpu);
        paramOut(cp, "vector", intMan[x].vector);
        paramOut(cp, "mask", intCtl[x].mask);
        paramOut(cp, "pend", intCtl[x].pend);
    };
    for (int x = 0; x < MaxNiagaraProcs; x++) {
        ScopedCheckpointSection sec(cp, csprintf("jIntBusy%d", x));
        paramOut(cp, "busy", jIntBusy[x].busy);
        paramOut(cp, "source", jIntBusy[x].source);
    };
}

void
Iob::unserialize(CheckpointIn &cp)
{
    UNSERIALIZE_SCALAR(jIntVec);
    UNSERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
    UNSERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
    for (int x = 0; x < NumDeviceIds; x++) {
        ScopedCheckpointSection sec(cp, csprintf("Int%d", x));
        paramIn(cp, "cpu", intMan[x].cpu);
        paramIn(cp, "vector", intMan[x].vector);
        paramIn(cp, "mask", intCtl[x].mask);
        paramIn(cp, "pend", intCtl[x].pend);
    };
    for (int x = 0; x < MaxNiagaraProcs; x++) {
        ScopedCheckpointSection sec(cp, csprintf("jIntBusy%d", x));
        paramIn(cp, "busy", jIntBusy[x].busy);
        paramIn(cp, "source", jIntBusy[x].source);
    };
}
