/*
 * 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->threadContexts.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->numContexts())
        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->threadContexts[cpu_id]);
        sys->threadContexts[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->threadContexts[cpu_id]->halt();
        break;
      case 3: // resume
        DPRINTF(Iob, "Resuming CPU because of I/O write cpu: %d\n", cpu_id);
        sys->threadContexts[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);
    };
}

Iob *
IobParams::create()
{
    return new Iob(this);
}
