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

#include "platform-bus.h"
#include "platform-proxy.h"

static i2c_txn_t* get_i2c_txn(platform_bus_t* bus, pdev_req_t* req, zx_handle_t channel) {
    mtx_lock(&bus->i2c_txn_lock);
    i2c_txn_t* txn = list_remove_head_type(&bus->i2c_txns, i2c_txn_t, node);
    mtx_unlock(&bus->i2c_txn_lock);

    if (!txn) {
        txn = malloc(sizeof(i2c_txn_t));
        if (!txn) {
            return NULL;
        }
    }

    txn->bus = bus;
    txn->txid = req->txid;
    txn->complete_cb = req->i2c.txn_ctx.complete_cb;
    txn->cookie = req->i2c.txn_ctx.cookie;
    txn->channel = channel;

    return txn;
}

static void put_i2c_txn(i2c_txn_t* txn) {
    platform_bus_t* bus = txn->bus;

    mtx_lock(&bus->i2c_txn_lock);
    list_add_tail(&bus->i2c_txns, &txn->node);
    mtx_unlock(&bus->i2c_txn_lock);
}

static zx_status_t platform_dev_get_mmio(platform_dev_t* dev, uint32_t index,
                                         zx_handle_t* out_handle, uint32_t* out_handle_count) {
    if (index >= dev->mmio_count) {
        return ZX_ERR_INVALID_ARGS;
    }

    pbus_mmio_t* mmio = &dev->mmios[index];
    zx_status_t status = zx_vmo_create_physical(dev->bus->resource, mmio->base, mmio->length,
                                                out_handle);
    if (status != ZX_OK) {
        zxlogf(ERROR, "platform_dev_map_mmio: zx_vmo_create_physical failed %d\n", status);
        return status;
    }
    *out_handle_count = 1;
    return ZX_OK;
}

static zx_status_t platform_dev_get_interrupt(platform_dev_t* dev, uint32_t index,
                                              zx_handle_t* out_handle, uint32_t* out_handle_count) {
    if (index >= dev->irq_count || !out_handle) {
        return ZX_ERR_INVALID_ARGS;
    }
    pbus_irq_t* irq = &dev->irqs[index];
    zx_status_t status = zx_interrupt_create(dev->bus->resource, irq->irq, ZX_INTERRUPT_REMAP_IRQ, out_handle);
    if (status != ZX_OK) {
        zxlogf(ERROR, "platform_dev_get_interrupt: zx_interrupt_create failed %d\n", status);
        return status;
    }
    *out_handle_count = 1;
    return ZX_OK;
}

static zx_status_t platform_dev_ums_get_initial_mode(platform_dev_t* dev, usb_mode_t* out_mode) {
    platform_bus_t* bus = dev->bus;
    if (!bus->ums.ops) {
        return ZX_ERR_NOT_SUPPORTED;
    }
    return usb_mode_switch_get_initial_mode(&bus->ums, out_mode);
}

static zx_status_t platform_dev_ums_set_mode(platform_dev_t* dev, usb_mode_t mode) {
    platform_bus_t* bus = dev->bus;
    if (!bus->ums.ops) {
        return ZX_ERR_NOT_SUPPORTED;
    }
    return usb_mode_switch_set_mode(&bus->ums, mode);
}

static zx_status_t platform_dev_gpio_config(platform_dev_t* dev, uint32_t index,
                                            gpio_config_flags_t flags) {
    platform_bus_t* bus = dev->bus;
    if (!bus->gpio.ops) {
        return ZX_ERR_NOT_SUPPORTED;
    }
    if (index >= dev->gpio_count) {
        return ZX_ERR_INVALID_ARGS;
    }
    index = dev->gpios[index].gpio;

    return gpio_config(&bus->gpio, index, flags);
}

static zx_status_t platform_dev_gpio_read(platform_dev_t* dev, uint32_t index, uint8_t* out_value) {
    platform_bus_t* bus = dev->bus;
    if (!bus->gpio.ops) {
        return ZX_ERR_NOT_SUPPORTED;
    }
    if (index >= dev->gpio_count) {
        return ZX_ERR_INVALID_ARGS;
    }
    index = dev->gpios[index].gpio;

    return gpio_read(&bus->gpio, index, out_value);
}

static zx_status_t platform_dev_gpio_write(platform_dev_t* dev, uint32_t index, uint8_t value) {
    platform_bus_t* bus = dev->bus;
    if (!bus->gpio.ops) {
        return ZX_ERR_NOT_SUPPORTED;
    }
    if (index >= dev->gpio_count) {
        return ZX_ERR_INVALID_ARGS;
    }
    index = dev->gpios[index].gpio;

    return gpio_write(&bus->gpio, index, value);
}

static zx_status_t platform_i2c_get_channel(platform_dev_t* dev, uint32_t index,
                                            pdev_i2c_resp_t* resp) {
    platform_bus_t* bus = dev->bus;
    if (!bus->i2c.ops) {
        return ZX_ERR_NOT_SUPPORTED;
    }
    if (index >= dev->i2c_channel_count) {
        return ZX_ERR_INVALID_ARGS;
    }
    pbus_i2c_channel_t* pdev_channel = &dev->i2c_channels[index];

    i2c_channel_t* channel = calloc(1, sizeof(i2c_channel_t));
    if (!channel) {
        return ZX_ERR_NO_MEMORY;
    }
    zx_status_t status = i2c_get_channel_by_address(&bus->i2c, pdev_channel->bus_id,
                                                    pdev_channel->address, channel);
    if (status == ZX_OK) {
        resp->server_ctx = channel;
    } else {
        free(channel);
        return status;
    }
    status = i2c_get_max_transfer_size(channel, &resp->max_transfer_size);
    if (status != ZX_OK) {
        i2c_channel_release(channel);
        free(channel);
        return status;
    }

    return ZX_OK;
}

static void platform_i2c_complete(zx_status_t status, const uint8_t* data, size_t actual,
                                  void* cookie) {
    i2c_txn_t* txn = cookie;

    if (actual > PDEV_I2C_MAX_TRANSFER_SIZE) {
        status = ZX_ERR_BUFFER_TOO_SMALL;
    }

    struct {
        pdev_resp_t resp;
        uint8_t data[PDEV_I2C_MAX_TRANSFER_SIZE];
    } resp = {
        .resp = {
            .txid = txn->txid,
            .status = status,
            .i2c = {
                .txn_ctx = {
                    .complete_cb = txn->complete_cb,
                    .cookie = txn->cookie,
                },
            },
        },
    };

    if (status == ZX_OK) {
        memcpy(resp.data, data, actual);
    }

    status = zx_channel_write(txn->channel, 0, &resp, sizeof(resp.resp) + actual, NULL, 0);
    if (status != ZX_OK) {
        zxlogf(ERROR, "platform_i2c_read_complete: zx_channel_write failed %d\n", status);
    }

    put_i2c_txn(txn);
}

static zx_status_t platform_i2c_transact(platform_dev_t* dev, pdev_req_t* req, uint8_t* data,
                                        zx_handle_t channel) {
    // TODO(voydanoff) Do not rely on client passing back a pointer to us.
    // We need a safer solution for this.
    i2c_channel_t* i2c_channel = (i2c_channel_t *)req->i2c.server_ctx;
    i2c_txn_t* txn = get_i2c_txn(dev->bus, req, channel);
    if (!txn) {
        return ZX_ERR_NO_MEMORY;
    }

    return i2c_transact(i2c_channel, data, req->i2c.txn_ctx.write_length,
                        req->i2c.txn_ctx.read_length, platform_i2c_complete, txn);
}

static zx_status_t platform_i2c_get_bitrate(platform_dev_t* dev, pdev_i2c_req_t* req,
                                            pdev_i2c_resp_t* resp) {
    i2c_channel_t* channel = (i2c_channel_t *)req->server_ctx;
    return i2c_set_bitrate(channel, req->bitrate);
}

static void platform_i2c_channel_release(platform_dev_t* dev, pdev_i2c_req_t* req) {
    i2c_channel_t* channel = (i2c_channel_t *)req->server_ctx;
    return i2c_channel_release(channel);
}

static zx_status_t platform_dev_rxrpc(void* ctx, zx_handle_t channel) {
    platform_dev_t* dev = ctx;
    struct {
        pdev_req_t req;
        uint8_t data[PDEV_I2C_MAX_TRANSFER_SIZE];
    } req_data;
    pdev_req_t* req = &req_data.req;
    pdev_resp_t resp;
    uint32_t len = sizeof(req_data);

    zx_status_t status = zx_channel_read(channel, 0, &req_data, NULL, len, 0, &len, NULL);
    if (status != ZX_OK) {
        zxlogf(ERROR, "platform_dev_rxrpc: zx_channel_read failed %d\n", status);
        return status;
    }

    resp.txid = req->txid;
    zx_handle_t handle = ZX_HANDLE_INVALID;
    uint32_t handle_count = 0;

    switch (req->op) {
    case PDEV_GET_MMIO:
        resp.status = platform_dev_get_mmio(dev, req->index, &handle, &handle_count);
        break;
    case PDEV_GET_INTERRUPT:
        resp.status = platform_dev_get_interrupt(dev, req->index, &handle, &handle_count);
        break;
    case PDEV_UMS_GET_INITIAL_MODE:
        resp.status = platform_dev_ums_get_initial_mode(dev, &resp.usb_mode);
        break;
    case PDEV_UMS_SET_MODE:
        resp.status = platform_dev_ums_set_mode(dev, req->usb_mode);
        break;
    case PDEV_GPIO_CONFIG:
        resp.status = platform_dev_gpio_config(dev, req->index, req->gpio_flags);
        break;
    case PDEV_GPIO_READ:
        resp.status = platform_dev_gpio_read(dev, req->index, &resp.gpio_value);
        break;
    case PDEV_GPIO_WRITE:
        resp.status = platform_dev_gpio_write(dev, req->index, req->gpio_value);
        break;
    case PDEV_I2C_GET_CHANNEL:
        resp.status = platform_i2c_get_channel(dev, req->index, &resp.i2c);
        break;
    case PDEV_I2C_TRANSACT:
        resp.status = platform_i2c_transact(dev, req, req_data.data, channel);
        if (resp.status == ZX_OK) {
            // If platform_i2c_transact succeeds, we return immmediately instead of calling
            // zx_channel_write below. Instead we will respond in platform_i2c_complete().
            return ZX_OK;
        }
        break;
    case PDEV_I2C_SET_BITRATE:
        resp.status = platform_i2c_get_bitrate(dev, &req->i2c, &resp.i2c);
        break;
    case PDEV_I2C_CHANNEL_RELEASE:
        platform_i2c_channel_release(dev, &req->i2c);
        break;
    default:
        zxlogf(ERROR, "platform_dev_rxrpc: unknown op %u\n", req->op);
        return ZX_ERR_INTERNAL;
    }

    // set op to match request so zx_channel_write will return our response
    status = zx_channel_write(channel, 0, &resp, sizeof(resp), (handle_count == 1 ? &handle : NULL),
                              handle_count);
    if (status != ZX_OK) {
        zxlogf(ERROR, "platform_dev_rxrpc: zx_channel_write failed %d\n", status);
    }
    return status;
}

void platform_dev_free(platform_dev_t* dev) {
    free(dev->mmios);
    free(dev->irqs);
    free(dev->gpios);
    free(dev->i2c_channels);
    free(dev);
}

static zx_protocol_device_t platform_dev_proto = {
    .version = DEVICE_OPS_VERSION,
    .rxrpc = platform_dev_rxrpc,
    // Note that we do not have a release callback here because we
    // need to support re-adding platform devices when they are reenabled.
};

zx_status_t platform_device_add(platform_bus_t* bus, const pbus_dev_t* pdev, uint32_t flags) {
    zx_status_t status = ZX_OK;

    if (flags & ~PDEV_ADD_DISABLED) {
        return ZX_ERR_INVALID_ARGS;
    }

    platform_dev_t* dev = calloc(1, sizeof(platform_dev_t));
    if (!dev) {
        return ZX_ERR_NO_MEMORY;
    }
    if (pdev->mmio_count) {
        size_t size = pdev->mmio_count * sizeof(*pdev->mmios);
        dev->mmios = malloc(size);
        if (!dev->mmios) {
            status = ZX_ERR_NO_MEMORY;
            goto fail;
        }
        memcpy(dev->mmios, pdev->mmios, size);
        dev->mmio_count = pdev->mmio_count;
    }
    if (pdev->irq_count) {
        size_t size = pdev->irq_count * sizeof(*pdev->irqs);
        dev->irqs = malloc(size);
        if (!dev->irqs) {
            status = ZX_ERR_NO_MEMORY;
            goto fail;
        }
        memcpy(dev->irqs, pdev->irqs, size);
        dev->irq_count = pdev->irq_count;
    }
    if (pdev->gpio_count) {
        size_t size = pdev->gpio_count * sizeof(*pdev->gpios);
        dev->gpios = malloc(size);
        if (!dev->gpios) {
            status = ZX_ERR_NO_MEMORY;
            goto fail;
        }
        memcpy(dev->gpios, pdev->gpios, size);
        dev->gpio_count = pdev->gpio_count;
    }
    if (pdev->i2c_channel_count) {
        size_t size = pdev->i2c_channel_count * sizeof(*pdev->i2c_channels);
        dev->i2c_channels = malloc(size);
        if (!dev->i2c_channels) {
            status = ZX_ERR_NO_MEMORY;
            goto fail;
        }
        memcpy(dev->i2c_channels, pdev->i2c_channels, size);
        dev->i2c_channel_count = pdev->i2c_channel_count;
    }

    dev->bus = bus;
    strlcpy(dev->name, pdev->name, sizeof(dev->name));
    dev->vid = pdev->vid;
    dev->pid = pdev->pid;
    dev->did = pdev->did;

    list_add_tail(&bus->devices, &dev->node);

    if ((flags & PDEV_ADD_DISABLED) == 0) {
        status = platform_device_enable(dev, true);
    }

fail:
    if (status != ZX_OK) {
        platform_dev_free(dev);
    }

    return status;
}

zx_status_t platform_device_enable(platform_dev_t* dev, bool enable) {
    zx_status_t status = ZX_OK;

    if (enable && !dev->enabled) {
        zx_device_prop_t props[] = {
            {BIND_PLATFORM_DEV_VID, 0, dev->vid},
            {BIND_PLATFORM_DEV_PID, 0, dev->pid},
            {BIND_PLATFORM_DEV_DID, 0, dev->did},
        };

        char namestr[ZX_DEVICE_NAME_MAX];
        snprintf(namestr, sizeof(namestr), "%04x:%04x:%04x", dev->vid, dev->pid, dev->did);
        char argstr[64];
        snprintf(argstr, sizeof(argstr), "pdev:%s,", namestr);

        device_add_args_t args = {
            .version = DEVICE_ADD_ARGS_VERSION,
            .name = namestr,
            .ctx = dev,
            .ops = &platform_dev_proto,
            .proto_id = ZX_PROTOCOL_PLATFORM_DEV,
            .props = props,
            .prop_count = countof(props),
            .proxy_args = argstr,
            .flags = DEVICE_ADD_MUST_ISOLATE,
        };
        // add PCI root at top level
        zx_device_t* parent = dev->bus->zxdev;
        if (dev->did == PDEV_DID_KPCI) {
            parent = device_get_parent(parent);
        }
        status = device_add(parent, &args, &dev->zxdev);
    } else if (!enable && dev->enabled) {
        device_remove(dev->zxdev);
        dev->zxdev = NULL;
    }

    if (status == ZX_OK) {
        dev->enabled = enable;
    }

    return status;
}
