// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <atomic>
#include <set>
#include <thread>

#include <ddk/binding.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/protocol/intelgpucore.h>
#include <fuchsia/gpu/magma/c/fidl.h>
#include <lib/zx/channel.h>
#include <zircon/process.h>
#include <zircon/types.h>

#include "magma_util/dlog.h"
#include "msd_intel_pci_device.h"
#include "platform_trace.h"
#include "sys_driver/magma_driver.h"

#if MAGMA_TEST_DRIVER
void magma_indriver_test(magma::PlatformPciDevice* platform_device);
#endif

struct sysdrv_device_t {
    zx_device_t* parent_device;
    zx_device_t* zx_device_gpu;

    zx_intel_gpu_core_protocol_t gpu_core_protocol;

    std::unique_ptr<MagmaDriver> magma_driver;
    std::shared_ptr<MagmaSystemDevice> magma_system_device;
    std::mutex magma_mutex;
};

static int magma_start(sysdrv_device_t* dev);

#if MAGMA_TEST_DRIVER
static int magma_stop(sysdrv_device_t* dev);
#endif

sysdrv_device_t* get_device(void* context) { return static_cast<sysdrv_device_t*>(context); }

// implement device protocol

static zx_status_t device_fidl_query(void* context, uint64_t query_id, fidl_txn_t* transaction)
{
    DLOG("device_fidl_query");
    sysdrv_device_t* device = get_device(context);

    uint64_t result;
    switch (query_id) {
        case MAGMA_QUERY_DEVICE_ID:
            result = device->magma_system_device->GetDeviceId();
            break;
        case MAGMA_QUERY_IS_TEST_RESTART_SUPPORTED:
#if MAGMA_TEST_DRIVER
            result = 1;
#else
            result = 0;
#endif
            break;
        default:
            if (!device->magma_system_device->Query(query_id, &result))
                return DRET_MSG(ZX_ERR_INVALID_ARGS, "unhandled query param 0x%" PRIx64, result);
    }
    DLOG("query query_id 0x%" PRIx64 " returning 0x%" PRIx64, query_id, result);

    zx_status_t status = fuchsia_gpu_magma_DeviceQuery_reply(transaction, result);
    if (status != ZX_OK)
        return DRET_MSG(ZX_ERR_INTERNAL, "magma_DeviceQuery_reply failed: %d", status);
    return ZX_OK;
}

static zx_status_t device_fidl_connect(void* context, uint64_t client_id, fidl_txn_t* transaction)
{
    DLOG("magma_DeviceConnectOrdinal");
    sysdrv_device_t* device = get_device(context);

    auto connection = MagmaSystemDevice::Open(device->magma_system_device, client_id);
    if (!connection)
        return DRET_MSG(ZX_ERR_INVALID_ARGS, "MagmaSystemDevice::Open failed");

    zx_status_t status = fuchsia_gpu_magma_DeviceConnect_reply(
        transaction, connection->GetClientEndpoint(), connection->GetClientNotificationEndpoint());
    if (status != ZX_OK)
        return DRET_MSG(ZX_ERR_INTERNAL, "magma_DeviceConnect_reply failed: %d", status);

    device->magma_system_device->StartConnectionThread(std::move(connection));
    return ZX_OK;
}

static zx_status_t device_fidl_dump_state(void* context, uint32_t dump_type)
{
    DLOG("device_fidl_dump_state");
    if (dump_type & ~(MAGMA_DUMP_TYPE_NORMAL | MAGMA_DUMP_TYPE_PERF_COUNTERS |
                      MAGMA_DUMP_TYPE_PERF_COUNTER_ENABLE))
        return DRET_MSG(ZX_ERR_INVALID_ARGS, "Invalid dump type %d", dump_type);

    sysdrv_device_t* device = get_device(context);
    std::unique_lock<std::mutex> lock(device->magma_mutex);
    if (device->magma_system_device)
        device->magma_system_device->DumpStatus(dump_type);
    return ZX_OK;
}

static zx_status_t device_fidl_test_restart(void* context)
{
#if MAGMA_TEST_DRIVER
    DLOG("device_fidl_test_restart");
    sysdrv_device_t* device = get_device(context);
    std::unique_lock<std::mutex> lock(device->magma_mutex);
    zx_status_t status = magma_stop(device);
    if (status != ZX_OK)
        return DRET_MSG(status, "magma_stop failed");
    return magma_start(device);
#else
    return ZX_ERR_NOT_SUPPORTED;
#endif
}

static fuchsia_gpu_magma_Device_ops_t device_fidl_ops = {
    .Query = device_fidl_query,
    .Connect = device_fidl_connect,
    .DumpState = device_fidl_dump_state,
    .TestRestart = device_fidl_test_restart,
};

static zx_status_t sysdrv_gpu_message(void* context, fidl_msg_t* message, fidl_txn_t* transaction)
{
    return fuchsia_gpu_magma_Device_dispatch(context, transaction, message, &device_fidl_ops);
}

static void sysdrv_gpu_release(void* ctx)
{
    // TODO(ZX-1170) - when testable:
    // Free context if sysdrv_display_release has already been called
    DASSERT(false);
}

static zx_protocol_device_t sysdrv_gpu_device_proto = {
    .version = DEVICE_OPS_VERSION,
    .message = sysdrv_gpu_message,
    .release = sysdrv_gpu_release,
};

// implement driver object:

static zx_status_t sysdrv_bind(void* ctx, zx_device_t* zx_device)
{
    DLOG("sysdrv_bind start zx_device %p", zx_device);

    // map resources and initialize the device
    auto device = std::make_unique<sysdrv_device_t>();

    zx_status_t status =
        device_get_protocol(zx_device, ZX_PROTOCOL_INTEL_GPU_CORE, &device->gpu_core_protocol);
    if (status != ZX_OK)
        return DRET_MSG(status, "device_get_protocol failed: %d", status);

    device->magma_driver = MagmaDriver::Create();
    if (!device->magma_driver)
        return DRET_MSG(ZX_ERR_INTERNAL, "MagmaDriver::Create failed");

    if (magma::PlatformTrace::Get())
        magma::PlatformTrace::Get()->Initialize();

#if MAGMA_TEST_DRIVER
    DLOG("running magma indriver test");
    {
        auto platform_device = MsdIntelPciDevice::CreateShim(&device->gpu_core_protocol);
        magma_indriver_test(platform_device.get());
    }
#endif

    device->parent_device = zx_device;

    status = magma_start(device.get());
    if (status != ZX_OK)
        return DRET_MSG(status, "magma_start failed");

    device_add_args_t args = {};
    args.version = DEVICE_ADD_ARGS_VERSION;
    args.name = "msd-intel-gen";
    args.ctx = device.get();
    args.ops = &sysdrv_gpu_device_proto;
    args.proto_id = ZX_PROTOCOL_GPU;
    args.proto_ops = nullptr;

    status = device_add(zx_device, &args, &device->zx_device_gpu);
    if (status != ZX_OK)
        return DRET_MSG(status, "gpu device_add failed: %d", status);

    device.release();

    DLOG("initialized magma system driver");

    return ZX_OK;
}

zx_driver_ops_t msd_driver_ops = {
    .version = DRIVER_OPS_VERSION,
    .bind = sysdrv_bind,
};

static int magma_start(sysdrv_device_t* device)
{
    DLOG("magma_start");

    device->magma_system_device = device->magma_driver->CreateDevice(&device->gpu_core_protocol);
    if (!device->magma_system_device)
        return DRET_MSG(ZX_ERR_NO_RESOURCES, "Failed to create device");

    DLOG("Created device %p", device->magma_system_device.get());

    return ZX_OK;
}

#if MAGMA_TEST_DRIVER
static int magma_stop(sysdrv_device_t* device)
{
    DLOG("magma_stop");

    device->magma_system_device->Shutdown();
    device->magma_system_device.reset();

    return ZX_OK;
}
#endif

// clang-format off
ZIRCON_DRIVER_BEGIN(gpu, msd_driver_ops, "magma", "0.1", 5)
    BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_INTEL_GPU_CORE),
ZIRCON_DRIVER_END(gpu)
