// 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 "src/devices/bus/drivers/platform/platform-proxy.h"

#include <lib/ddk/debug.h>
#include <lib/zircon-internal/align.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>

#include <utility>

#include <fbl/algorithm.h>
#include <fbl/auto_lock.h>

#include "src/devices/bus/drivers/platform/platform-bus-bind.h"

namespace platform_bus {

void PlatformProxy::DdkRelease() { delete this; }

zx_status_t PlatformProxy::PDevGetMmio(uint32_t index, pdev_mmio_t* out_mmio) {
  if (index >= mmios_.size()) {
    return ZX_ERR_OUT_OF_RANGE;
  }

  const Mmio& mmio = mmios_[index];
  const zx_paddr_t vmo_base = ZX_ROUNDDOWN(mmio.base, ZX_PAGE_SIZE);
  const size_t vmo_size = ZX_ROUNDUP(mmio.base + mmio.length - vmo_base, ZX_PAGE_SIZE);
  zx::vmo vmo;

  zx_status_t status = zx::vmo::create_physical(mmio.resource, vmo_base, vmo_size, &vmo);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s %s: creating vmo failed %d", name_, __FUNCTION__, status);
    return status;
  }

  char name[32];
  snprintf(name, sizeof(name), "%s mmio %u", name_, index);
  status = vmo.set_property(ZX_PROP_NAME, name, sizeof(name));
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s %s: setting vmo name failed %d", name_, __FUNCTION__, status);
    return status;
  }

  out_mmio->offset = mmio.base - vmo_base;
  out_mmio->vmo = vmo.release();
  out_mmio->size = mmio.length;
  return ZX_OK;
}

zx_status_t PlatformProxy::PDevGetInterrupt(uint32_t index, uint32_t flags,
                                            zx::interrupt* out_irq) {
  if (index >= irqs_.size()) {
    return ZX_ERR_OUT_OF_RANGE;
  }

  Irq* irq = &irqs_[index];
  if (flags == 0) {
    flags = irq->mode;
  }
  zx_status_t status = zx::interrupt::create(irq->resource, irq->irq, flags, out_irq);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s %s: creating interrupt failed: %d", name_, __FUNCTION__, status);
    return status;
  }

  return ZX_OK;
}

zx_status_t PlatformProxy::PDevGetBti(uint32_t index, zx::bti* out_bti) {
  rpc_pdev_req_t req = {};
  rpc_pdev_rsp_t resp = {};
  req.header.op = PDEV_GET_BTI;
  req.index = index;

  return Rpc(&req.header, sizeof(req), &resp.header, sizeof(resp), nullptr, 0,
             out_bti->reset_and_get_address(), 1, nullptr);
}

zx_status_t PlatformProxy::PDevGetSmc(uint32_t index, zx::resource* out_resource) {
  rpc_pdev_req_t req = {};
  rpc_pdev_rsp_t resp = {};
  req.header.op = PDEV_GET_SMC;
  req.index = index;

  return Rpc(&req.header, sizeof(req), &resp.header, sizeof(resp), nullptr, 0,
             out_resource->reset_and_get_address(), 1, nullptr);
}

zx_status_t PlatformProxy::PDevGetDeviceInfo(pdev_device_info_t* out_info) {
  rpc_pdev_req_t req = {};
  rpc_pdev_rsp_t resp = {};
  req.header.op = PDEV_GET_DEVICE_INFO;

  auto status = Rpc(&req.header, sizeof(req), &resp.header, sizeof(resp));
  if (status != ZX_OK) {
    return status;
  }
  memcpy(out_info, &resp.device_info, sizeof(*out_info));
  return ZX_OK;
}

zx_status_t PlatformProxy::PDevGetBoardInfo(pdev_board_info_t* out_info) {
  rpc_pdev_req_t req = {};
  rpc_pdev_rsp_t resp = {};
  req.header.op = PDEV_GET_BOARD_INFO;

  auto status = Rpc(&req.header, sizeof(req), &resp.header, sizeof(resp));
  if (status != ZX_OK) {
    return status;
  }
  memcpy(out_info, &resp.board_info, sizeof(*out_info));
  return ZX_OK;
}

zx_status_t PlatformProxy::Rpc(const platform_proxy_req_t* req, size_t req_length,
                               platform_proxy_rsp_t* resp, size_t resp_length,
                               const zx_handle_t* in_handles, size_t in_handle_count,
                               zx_handle_t* out_handles, size_t out_handle_count,
                               size_t* out_actual) {
  uint32_t resp_size, handle_count;

  zx_channel_call_args_t args = {
      .wr_bytes = req,
      .wr_handles = in_handles,
      .rd_bytes = resp,
      .rd_handles = out_handles,
      .wr_num_bytes = static_cast<uint32_t>(req_length),
      .wr_num_handles = static_cast<uint32_t>(in_handle_count),
      .rd_num_bytes = static_cast<uint32_t>(resp_length),
      .rd_num_handles = static_cast<uint32_t>(out_handle_count),
  };
  auto status = rpc_channel_.call(0, zx::time::infinite(), &args, &resp_size, &handle_count);
  if (status != ZX_OK) {
    // This is a fairly serious error; subsequent requests are very likely
    // to also fail.
    //
    // TODO(fxbug.dev/33622): Make this less likely and/or handle differently.
    zxlogf(ERROR, "PlatformProxy::Rpc rpc_channel_.call failed - status: %d", status);
    return status;
  }

  status = resp->status;

  if (status == ZX_OK && resp_size < sizeof(*resp)) {
    zxlogf(ERROR, "PlatformProxy::Rpc resp_size too short: %u", resp_size);
    status = ZX_ERR_INTERNAL;
    goto fail;
  } else if (status == ZX_OK && handle_count != out_handle_count) {
    zxlogf(ERROR, "PlatformProxy::Rpc handle count %u expected %zu", handle_count,
           out_handle_count);
    status = ZX_ERR_INTERNAL;
    goto fail;
  }

  if (out_actual) {
    *out_actual = resp_size;
  }

fail:
  if (status != ZX_OK) {
    for (uint32_t i = 0; i < handle_count; i++) {
      zx_handle_close(out_handles[i]);
    }
  }
  return status;
}

zx_status_t PlatformProxy::Create(void* ctx, zx_device_t* parent, const char* name,
                                  const char* args, zx_handle_t rpc_channel) {
  fbl::AllocChecker ac;

  auto proxy = fbl::make_unique_checked<PlatformProxy>(&ac, parent, rpc_channel);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  auto status = proxy->Init(parent);
  if (status != ZX_OK) {
    return status;
  }

  // devmgr is now in charge of the device.
  __UNUSED auto* dummy = proxy.release();

  return ZX_OK;
}

zx_status_t PlatformProxy::Init(zx_device_t* parent) {
  pdev_device_info_t info;
  auto status = PDevGetDeviceInfo(&info);
  if (status != ZX_OK) {
    return status;
  }
  memcpy(name_, info.name, sizeof(name_));
  metadata_count_ = info.metadata_count;

  fbl::AllocChecker ac;

  for (uint32_t i = 0; i < info.mmio_count; i++) {
    rpc_pdev_req_t req = {};
    rpc_pdev_rsp_t resp = {};
    zx_handle_t rsrc_handle;

    req.header.op = PDEV_GET_MMIO;
    req.index = i;
    status =
        Rpc(&req.header, sizeof(req), &resp.header, sizeof(resp), NULL, 0, &rsrc_handle, 1, NULL);
    if (status != ZX_OK) {
      return status;
    }

    Mmio mmio;
    mmio.base = resp.paddr;
    mmio.length = resp.length;
    mmio.resource.reset(rsrc_handle);
    mmios_.push_back(std::move(mmio), &ac);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }

    zxlogf(TRACE, "%s: received MMIO %u (base %#lx length %#lx handle %#x)", name_, i, mmio.base,
           mmio.length, mmio.resource.get());
  }

  for (uint32_t i = 0; i < info.irq_count; i++) {
    rpc_pdev_req_t req = {};
    rpc_pdev_rsp_t resp = {};
    zx_handle_t rsrc_handle;

    req.header.op = PDEV_GET_INTERRUPT;
    req.index = i;
    status =
        Rpc(&req.header, sizeof(req), &resp.header, sizeof(resp), NULL, 0, &rsrc_handle, 1, NULL);
    if (status != ZX_OK) {
      return status;
    }

    Irq irq;
    irq.irq = resp.irq;
    irq.mode = resp.mode;
    irq.resource.reset(rsrc_handle);
    irqs_.push_back(std::move(irq), &ac);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }

    zxlogf(TRACE, "%s: received IRQ %u (irq %#x handle %#x)", name_, i, irq.irq,
           irq.resource.get());
  }

  return DdkAdd(name_);
}

static constexpr zx_driver_ops_t proxy_driver_ops = []() {
  zx_driver_ops_t ops = {};
  ops.version = DRIVER_OPS_VERSION;
  ops.create = PlatformProxy::Create;
  return ops;
}();

}  // namespace platform_bus

ZIRCON_DRIVER(platform_bus_proxy, platform_bus::proxy_driver_ops, "zircon", "0.1");
