/*
 * 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: Ali Saidi
 */

/** @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 <cstring>

#include "arch/sparc/faults.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/sparc/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->set(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->set(data);
            return;
        }

        if (accessAddr == JIntVecAddr) {
            pkt->set(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->set(jBusData0[index]);
            return;
        }

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

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

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

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