/*
 * QEMU Apple ParavirtualizedGraphics.framework device, PCI variant
 *
 * Copyright © 2023-2024 Phil Dennis-Jordan
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * ParavirtualizedGraphics.framework is a set of libraries that macOS provides
 * which implements 3d graphics passthrough to the host as well as a
 * proprietary guest communication channel to drive it. This device model
 * implements support to drive that library from within QEMU as a PCI device
 * aimed primarily at x86-64 macOS VMs.
 */

#include "qemu/osdep.h"
#include "hw/pci/pci_device.h"
#include "hw/pci/msi.h"
#include "apple-gfx.h"
#include "trace.h"

#import <ParavirtualizedGraphics/ParavirtualizedGraphics.h>

OBJECT_DECLARE_SIMPLE_TYPE(AppleGFXPCIState, APPLE_GFX_PCI)

struct AppleGFXPCIState {
    PCIDevice parent_obj;

    AppleGFXState common;
};

static const char *apple_gfx_pci_option_rom_path = NULL;

static void apple_gfx_init_option_rom_path(void)
{
    NSURL *option_rom_url = PGCopyOptionROMURL();
    const char *option_rom_path = option_rom_url.fileSystemRepresentation;
    apple_gfx_pci_option_rom_path = g_strdup(option_rom_path);
    [option_rom_url release];
}

static void apple_gfx_pci_init(Object *obj)
{
    AppleGFXPCIState *s = APPLE_GFX_PCI(obj);

    if (!apple_gfx_pci_option_rom_path) {
        /*
         * The following is done on device not class init to avoid running
         * ObjC code before fork() in -daemonize mode.
         */
        PCIDeviceClass *pci = PCI_DEVICE_CLASS(object_get_class(obj));
        apple_gfx_init_option_rom_path();
        pci->romfile = apple_gfx_pci_option_rom_path;
    }

    apple_gfx_common_init(obj, &s->common, TYPE_APPLE_GFX_PCI);
}

typedef struct AppleGFXPCIInterruptJob {
    PCIDevice *device;
    uint32_t vector;
} AppleGFXPCIInterruptJob;

static void apple_gfx_pci_raise_interrupt(void *opaque)
{
    AppleGFXPCIInterruptJob *job = opaque;

    if (msi_enabled(job->device)) {
        msi_notify(job->device, job->vector);
    }
    g_free(job);
}

static void apple_gfx_pci_interrupt(PCIDevice *dev, uint32_t vector)
{
    AppleGFXPCIInterruptJob *job;

    trace_apple_gfx_raise_irq(vector);
    job = g_malloc0(sizeof(*job));
    job->device = dev;
    job->vector = vector;
    aio_bh_schedule_oneshot(qemu_get_aio_context(),
                            apple_gfx_pci_raise_interrupt, job);
}

static void apple_gfx_pci_realize(PCIDevice *dev, Error **errp)
{
    AppleGFXPCIState *s = APPLE_GFX_PCI(dev);
    int ret;

    pci_register_bar(dev, PG_PCI_BAR_MMIO,
                     PCI_BASE_ADDRESS_SPACE_MEMORY, &s->common.iomem_gfx);

    ret = msi_init(dev, 0x0 /* config offset; 0 = find space */,
                   PG_PCI_MAX_MSI_VECTORS, true /* msi64bit */,
                   false /* msi_per_vector_mask */, errp);
    if (ret != 0) {
        return;
    }

    @autoreleasepool {
        PGDeviceDescriptor *desc = [PGDeviceDescriptor new];
        desc.raiseInterrupt = ^(uint32_t vector) {
            apple_gfx_pci_interrupt(dev, vector);
        };

        apple_gfx_common_realize(&s->common, DEVICE(dev), desc, errp);
        [desc release];
        desc = nil;
    }
}

static void apple_gfx_pci_reset(Object *obj, ResetType type)
{
    AppleGFXPCIState *s = APPLE_GFX_PCI(obj);
    [s->common.pgdev reset];
}

static const Property apple_gfx_pci_properties[] = {
    DEFINE_PROP_ARRAY("display-modes", AppleGFXPCIState,
                      common.num_display_modes, common.display_modes,
                      qdev_prop_apple_gfx_display_mode, AppleGFXDisplayMode),
};

static void apple_gfx_pci_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    PCIDeviceClass *pci = PCI_DEVICE_CLASS(klass);
    ResettableClass *rc = RESETTABLE_CLASS(klass);

    rc->phases.hold = apple_gfx_pci_reset;
    dc->desc = "macOS Paravirtualized Graphics PCI Display Controller";
    dc->hotpluggable = false;
    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);

    pci->vendor_id = PG_PCI_VENDOR_ID;
    pci->device_id = PG_PCI_DEVICE_ID;
    pci->class_id = PCI_CLASS_DISPLAY_OTHER;
    pci->realize = apple_gfx_pci_realize;

    device_class_set_props(dc, apple_gfx_pci_properties);
}

static const TypeInfo apple_gfx_pci_types[] = {
    {
        .name          = TYPE_APPLE_GFX_PCI,
        .parent        = TYPE_PCI_DEVICE,
        .instance_size = sizeof(AppleGFXPCIState),
        .class_init    = apple_gfx_pci_class_init,
        .instance_init = apple_gfx_pci_init,
        .interfaces = (InterfaceInfo[]) {
            { INTERFACE_PCIE_DEVICE },
            { },
        },
    }
};
DEFINE_TYPES(apple_gfx_pci_types)

