/*
 * QEMU Generic PCIE-PCI Bridge
 *
 * Copyright (c) 2017 Aleksandr Bezzubikov
 *
 * 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 "qapi/error.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_bus.h"
#include "hw/pci/pci_bridge.h"
#include "hw/pci/msi.h"
#include "hw/pci/shpc.h"
#include "hw/pci/slotid_cap.h"

typedef struct PCIEPCIBridge {
    /*< private >*/
    PCIBridge parent_obj;

    OnOffAuto msi;
    MemoryRegion shpc_bar;
    /*< public >*/
} PCIEPCIBridge;

#define TYPE_PCIE_PCI_BRIDGE_DEV "pcie-pci-bridge"
#define PCIE_PCI_BRIDGE_DEV(obj) \
        OBJECT_CHECK(PCIEPCIBridge, (obj), TYPE_PCIE_PCI_BRIDGE_DEV)

static void pcie_pci_bridge_realize(PCIDevice *d, Error **errp)
{
    PCIBridge *br = PCI_BRIDGE(d);
    PCIEPCIBridge *pcie_br = PCIE_PCI_BRIDGE_DEV(d);
    int rc, pos;

    pci_bridge_initfn(d, TYPE_PCI_BUS);

    d->config[PCI_INTERRUPT_PIN] = 0x1;
    memory_region_init(&pcie_br->shpc_bar, OBJECT(d), "shpc-bar",
                       shpc_bar_size(d));
    rc = shpc_init(d, &br->sec_bus, &pcie_br->shpc_bar, 0, errp);
    if (rc) {
        goto error;
    }

    rc = pcie_cap_init(d, 0, PCI_EXP_TYPE_PCI_BRIDGE, 0, errp);
    if (rc < 0) {
        goto cap_error;
    }

    pos = pci_add_capability(d, PCI_CAP_ID_PM, 0, PCI_PM_SIZEOF, errp);
    if (pos < 0) {
        goto pm_error;
    }
    d->exp.pm_cap = pos;
    pci_set_word(d->config + pos + PCI_PM_PMC, 0x3);

    pcie_cap_arifwd_init(d);
    pcie_cap_deverr_init(d);

    rc = pcie_aer_init(d, PCI_ERR_VER, 0x100, PCI_ERR_SIZEOF, errp);
    if (rc < 0) {
        goto aer_error;
    }

    Error *local_err = NULL;
    if (pcie_br->msi != ON_OFF_AUTO_OFF) {
        rc = msi_init(d, 0, 1, true, true, &local_err);
        if (rc < 0) {
            assert(rc == -ENOTSUP);
            if (pcie_br->msi != ON_OFF_AUTO_ON) {
                error_free(local_err);
            } else {
                /* failed to satisfy user's explicit request for MSI */
                error_propagate(errp, local_err);
                goto msi_error;
            }
        }
    }
    pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
                     PCI_BASE_ADDRESS_MEM_TYPE_64, &pcie_br->shpc_bar);
    return;

msi_error:
    pcie_aer_exit(d);
aer_error:
pm_error:
    pcie_cap_exit(d);
cap_error:
    shpc_cleanup(d, &pcie_br->shpc_bar);
error:
    pci_bridge_exitfn(d);
}

static void pcie_pci_bridge_exit(PCIDevice *d)
{
    PCIEPCIBridge *bridge_dev = PCIE_PCI_BRIDGE_DEV(d);
    pcie_cap_exit(d);
    shpc_cleanup(d, &bridge_dev->shpc_bar);
    pci_bridge_exitfn(d);
}

static void pcie_pci_bridge_reset(DeviceState *qdev)
{
    PCIDevice *d = PCI_DEVICE(qdev);
    pci_bridge_reset(qdev);
    if (msi_present(d)) {
        msi_reset(d);
    }
    shpc_reset(d);
}

static void pcie_pci_bridge_write_config(PCIDevice *d,
        uint32_t address, uint32_t val, int len)
{
    pci_bridge_write_config(d, address, val, len);
    if (msi_present(d)) {
        msi_write_config(d, address, val, len);
    }
    shpc_cap_write_config(d, address, val, len);
}

static Property pcie_pci_bridge_dev_properties[] = {
        DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi, ON_OFF_AUTO_AUTO),
        DEFINE_PROP_END_OF_LIST(),
};

static const VMStateDescription pcie_pci_bridge_dev_vmstate = {
        .name = TYPE_PCIE_PCI_BRIDGE_DEV,
        .fields = (VMStateField[]) {
            VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
            SHPC_VMSTATE(shpc, PCIDevice, NULL),
            VMSTATE_END_OF_LIST()
        }
};

static void pcie_pci_bridge_hotplug_cb(HotplugHandler *hotplug_dev,
                                      DeviceState *dev, Error **errp)
{
    PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);

    if (!shpc_present(pci_hotplug_dev)) {
        error_setg(errp, "standard hotplug controller has been disabled for "
                   "this %s", TYPE_PCIE_PCI_BRIDGE_DEV);
        return;
    }
    shpc_device_hotplug_cb(hotplug_dev, dev, errp);
}

static void pcie_pci_bridge_hot_unplug_request_cb(HotplugHandler *hotplug_dev,
                                                 DeviceState *dev,
                                                 Error **errp)
{
    PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);

    if (!shpc_present(pci_hotplug_dev)) {
        error_setg(errp, "standard hotplug controller has been disabled for "
                   "this %s", TYPE_PCIE_PCI_BRIDGE_DEV);
        return;
    }
    shpc_device_hot_unplug_request_cb(hotplug_dev, dev, errp);
}

static void pcie_pci_bridge_class_init(ObjectClass *klass, void *data)
{
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
    DeviceClass *dc = DEVICE_CLASS(klass);
    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);

    k->is_express = 1;
    k->is_bridge = 1;
    k->vendor_id = PCI_VENDOR_ID_REDHAT;
    k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE;
    k->realize = pcie_pci_bridge_realize;
    k->exit = pcie_pci_bridge_exit;
    k->config_write = pcie_pci_bridge_write_config;
    dc->vmsd = &pcie_pci_bridge_dev_vmstate;
    dc->props = pcie_pci_bridge_dev_properties;
    dc->vmsd = &pcie_pci_bridge_dev_vmstate;
    dc->reset = &pcie_pci_bridge_reset;
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
    hc->plug = pcie_pci_bridge_hotplug_cb;
    hc->unplug_request = pcie_pci_bridge_hot_unplug_request_cb;
}

static const TypeInfo pcie_pci_bridge_info = {
        .name = TYPE_PCIE_PCI_BRIDGE_DEV,
        .parent = TYPE_PCI_BRIDGE,
        .instance_size = sizeof(PCIEPCIBridge),
        .class_init = pcie_pci_bridge_class_init,
        .interfaces = (InterfaceInfo[]) {
            { TYPE_HOTPLUG_HANDLER },
            { INTERFACE_PCIE_DEVICE },
            { },
        }
};

static void pciepci_register(void)
{
    type_register_static(&pcie_pci_bridge_info);
}

type_init(pciepci_register);
