/*
 * 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 "qemu/module.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"
#include "hw/qdev-properties.h"
#include "qom/object.h"

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

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

#define TYPE_PCIE_PCI_BRIDGE_DEV "pcie-pci-bridge"
OBJECT_DECLARE_SIMPLE_TYPE(PCIEPCIBridge, 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_pm_init(d, 0, errp);
    if (pos < 0) {
        goto pm_error;
    }
    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 const Property pcie_pci_bridge_dev_properties[] = {
        DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi, ON_OFF_AUTO_AUTO),
};

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

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->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;
    device_class_set_props(dc, pcie_pci_bridge_dev_properties);
    device_class_set_legacy_reset(dc, pcie_pci_bridge_reset);
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
    hc->plug = pci_bridge_dev_plug_cb;
    hc->unplug = pci_bridge_dev_unplug_cb;
    hc->unplug_request = pci_bridge_dev_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);
