/*
 * 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_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,
        .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);
    dc->reset = &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);
