// Copyright 2018 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 <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/platform-defs.h>
#include <ddk/protocol/platform/device.h>
#include <stdlib.h>
#include <string.h>

typedef struct cpu_trace_dev {
    zx_device_t* zxdev;
    zx_handle_t bti;
} cpu_trace_dev_t;

static const pdev_device_info_t cpu_trace_pdev_device_info = {
    .vid = PDEV_VID_INTEL,
    .pid = PDEV_PID_GENERIC,
    .did = PDEV_DID_INTEL_CPU_TRACE,
    .bti_count = 1,
};

static zx_status_t cpu_trace_get_bti(void* ctx, uint32_t index, zx_handle_t* out_handle) {
    cpu_trace_dev_t* dev = ctx;
    if (index >= cpu_trace_pdev_device_info.bti_count || out_handle == NULL) {
        return ZX_ERR_INVALID_ARGS;
    }
    return zx_handle_duplicate(dev->bti, ZX_RIGHT_SAME_RIGHTS, out_handle);
}

static zx_status_t cpu_trace_get_device_info(void* ctx, pdev_device_info_t* out_info) {
    memcpy(out_info, &cpu_trace_pdev_device_info, sizeof(*out_info));
    return ZX_OK;
}

static zx_status_t cpu_trace_get_mmio(void* ctx, uint32_t index, pdev_mmio_t* mmio) {
    return ZX_ERR_NOT_SUPPORTED;
}

static zx_status_t cpu_trace_get_interrupt(void* ctx, uint32_t index, uint32_t flags, zx_handle_t* out_handle) {
    return ZX_ERR_NOT_SUPPORTED;
}

static pdev_protocol_ops_t cpu_trace_proto_ops = {
    .get_mmio = cpu_trace_get_mmio,
    .get_interrupt = cpu_trace_get_interrupt,
    .get_bti = cpu_trace_get_bti,
    .get_device_info = cpu_trace_get_device_info,
};


static void cpu_trace_release(void* ctx) {
    cpu_trace_dev_t* dev = ctx;
    zx_handle_close(dev->bti);
    free(dev);
}

static zx_protocol_device_t cpu_trace_dev_proto = {
    .version = DEVICE_OPS_VERSION,
    .release = cpu_trace_release,
};

zx_status_t publish_cpu_trace(zx_handle_t bti, zx_device_t* sys_root) {
    cpu_trace_dev_t* dev = calloc(1, sizeof(*dev));
    if (dev == NULL) {
        return ZX_ERR_NO_MEMORY;
    }
    dev->bti = bti;

    zx_device_prop_t props[] = {
        {BIND_PLATFORM_DEV_VID, 0, cpu_trace_pdev_device_info.vid},
        {BIND_PLATFORM_DEV_PID, 0, cpu_trace_pdev_device_info.pid},
        {BIND_PLATFORM_DEV_DID, 0, cpu_trace_pdev_device_info.did},
    };
    device_add_args_t args = {
        .version = DEVICE_ADD_ARGS_VERSION,
        .name = "cpu-trace",
        .ctx = dev,
        .ops = &cpu_trace_dev_proto,
        .proto_id = ZX_PROTOCOL_PDEV,
        .proto_ops = &cpu_trace_proto_ops,
        .props = props,
        .prop_count = countof(props),
        .proxy_args = NULL,
        .flags = 0,
    };

    // add as a child of the sysroot
    zx_status_t status = device_add(sys_root, &args, &dev->zxdev);
    if (status != ZX_OK) {
        zxlogf(ERROR, "acpi-bus: error %d in device_add(sys/cpu-trace)\n", status);
        cpu_trace_release(dev);
        return status;
    }

    return ZX_OK;
}
