/*
 * Remote IO Hub
 *
 * Copyright © 2018, 2021 Oracle and/or its affiliates.
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 *
 */

#include "qemu/osdep.h"

#include "hw/pci/pci.h"
#include "hw/pci/pci_ids.h"
#include "hw/pci/pci_bus.h"
#include "qemu/thread.h"
#include "hw/remote/machine.h"
#include "hw/remote/iohub.h"
#include "qemu/main-loop.h"

void remote_iohub_init(RemoteIOHubState *iohub)
{
    int pirq;

    memset(&iohub->irqfds, 0, sizeof(iohub->irqfds));
    memset(&iohub->resamplefds, 0, sizeof(iohub->resamplefds));

    for (pirq = 0; pirq < REMOTE_IOHUB_NB_PIRQS; pirq++) {
        qemu_mutex_init(&iohub->irq_level_lock[pirq]);
        iohub->irq_level[pirq] = 0;
        event_notifier_init_fd(&iohub->irqfds[pirq], -1);
        event_notifier_init_fd(&iohub->resamplefds[pirq], -1);
    }
}

int remote_iohub_map_irq(PCIDevice *pci_dev, int intx)
{
    return pci_dev->devfn;
}

void remote_iohub_set_irq(void *opaque, int pirq, int level)
{
    RemoteIOHubState *iohub = opaque;

    assert(pirq >= 0);
    assert(pirq < PCI_DEVFN_MAX);

    QEMU_LOCK_GUARD(&iohub->irq_level_lock[pirq]);

    if (level) {
        if (++iohub->irq_level[pirq] == 1) {
            event_notifier_set(&iohub->irqfds[pirq]);
        }
    } else if (iohub->irq_level[pirq] > 0) {
        iohub->irq_level[pirq]--;
    }
}

static void intr_resample_handler(void *opaque)
{
    ResampleToken *token = opaque;
    RemoteIOHubState *iohub = token->iohub;
    int pirq, s;

    pirq = token->pirq;

    s = event_notifier_test_and_clear(&iohub->resamplefds[pirq]);

    assert(s >= 0);

    QEMU_LOCK_GUARD(&iohub->irq_level_lock[pirq]);

    if (iohub->irq_level[pirq]) {
        event_notifier_set(&iohub->irqfds[pirq]);
    }
}

void process_set_irqfd_msg(PCIDevice *pci_dev, MPQemuMsg *msg)
{
    RemoteMachineState *machine = REMOTE_MACHINE(current_machine);
    RemoteIOHubState *iohub = &machine->iohub;
    int pirq, intx;

    intx = pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1;

    pirq = remote_iohub_map_irq(pci_dev, intx);

    if (event_notifier_get_fd(&iohub->irqfds[pirq]) != -1) {
        qemu_set_fd_handler(event_notifier_get_fd(&iohub->resamplefds[pirq]),
                            NULL, NULL, NULL);
        event_notifier_cleanup(&iohub->irqfds[pirq]);
        event_notifier_cleanup(&iohub->resamplefds[pirq]);
        memset(&iohub->token[pirq], 0, sizeof(ResampleToken));
    }

    event_notifier_init_fd(&iohub->irqfds[pirq], msg->fds[0]);
    event_notifier_init_fd(&iohub->resamplefds[pirq], msg->fds[1]);

    iohub->token[pirq].iohub = iohub;
    iohub->token[pirq].pirq = pirq;

    qemu_set_fd_handler(msg->fds[1], intr_resample_handler, NULL,
                        &iohub->token[pirq]);
}
