// Copyright 2016 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 <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zircon/assert.h>
#include <zircon/fidl.h>
#include <zircon/process.h>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/driver.h>
#include <ddk/protocol/pci.h>
#include <ddk/protocol/sysmem.h>
#include <hw/pci.h>

#include "kpci-private.h"

zx_status_t pci_rpc_request(kpci_device_t* dev, uint32_t op, zx_handle_t* handle, pci_msg_t* req,
                            pci_msg_t* resp) {
  if (dev->pciroot_rpcch == ZX_HANDLE_INVALID) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  uint32_t in_handle_cnt = (op == PCI_OP_CONNECT_SYSMEM) ? 1 : 0;

  uint32_t handle_cnt = 0;
  if (handle) {
    // Since only the caller knows if they expected a valid handle back, make
    // sure the handle reads INVALID if we didn't get one.
    *handle = ZX_HANDLE_INVALID;
    handle_cnt = 1;
  }

  req->hdr.ordinal = op;
  zx_channel_call_args_t cc_args = {
      .wr_bytes = req,
      .rd_bytes = resp,
      .rd_handles = handle,
      .wr_num_bytes = sizeof(*req),
      .rd_num_bytes = sizeof(*resp),
      .rd_num_handles = handle_cnt,
      .wr_handles = in_handle_cnt ? &req->handle : NULL,
      .wr_num_handles = in_handle_cnt,
  };

  uint32_t actual_bytes;
  uint32_t actual_handles;
  zx_status_t st = zx_channel_call(dev->pciroot_rpcch, 0, ZX_TIME_INFINITE, &cc_args, &actual_bytes,
                                   &actual_handles);
  if (st != ZX_OK) {
    return st;
  }

  if (actual_bytes != sizeof(*resp)) {
    return ZX_ERR_INTERNAL;
  }

  return (zx_status_t)resp->hdr.ordinal;
}

// pci_op_* methods are called by the proxy devhost. For each PCI
// protocol method there is generally a pci_op_* method for the proxy
// devhost and a corresponding kpci_* method in the top devhost that the
// protocol request is handled by.

// Enables or disables bus mastering for a particular device.
static zx_status_t pci_op_enable_bus_master(void* ctx, bool enable) {
  kpci_device_t* dev = ctx;
  pci_msg_t req = {
      .enable = enable,
  };
  pci_msg_t resp = {};

  return pci_rpc_request(dev, PCI_OP_ENABLE_BUS_MASTER, NULL, &req, &resp);
}

// Resets the device.
static zx_status_t pci_op_reset_device(void* ctx) {
  kpci_device_t* dev = ctx;
  pci_msg_t req = {};
  pci_msg_t resp = {};

  return pci_rpc_request(dev, PCI_OP_RESET_DEVICE, NULL, &req, &resp);
}

// These reads are proxied directly over to the device's PciConfig object so the validity of the
// widths and offsets will be validated on that end and then trickle back to this level of the
// protocol.
static zx_status_t pci_op_config_read(void* ctx, uint16_t offset, size_t width, uint32_t* val) {
  kpci_device_t* dev = ctx;
  if (width > sizeof(uint32_t) || val == NULL) {
    return ZX_ERR_INVALID_ARGS;
  }

  pci_msg_t req = {
      .cfg =
          {
              .offset = offset,
              .width = (uint16_t)width,
          },
  };
  pci_msg_t resp = {};
  zx_status_t st = pci_rpc_request(dev, PCI_OP_CONFIG_READ, NULL, &req, &resp);
  if (st == ZX_OK) {
    *val = resp.cfg.value;
  }
  return st;
}

static zx_status_t pci_op_config_read8(void* ctx, uint16_t offset, uint8_t* val) {
  uint32_t tmp;
  zx_status_t st = pci_op_config_read(ctx, offset, sizeof(*val), &tmp);
  *val = tmp & UINT8_MAX;
  return st;
}

static zx_status_t pci_op_config_read16(void* ctx, uint16_t offset, uint16_t* val) {
  uint32_t tmp;
  zx_status_t st = pci_op_config_read(ctx, offset, sizeof(*val), &tmp);
  *val = tmp & UINT16_MAX;
  return st;
}

static zx_status_t pci_op_config_read32(void* ctx, uint16_t offset, uint32_t* val) {
  return pci_op_config_read(ctx, offset, sizeof(uint32_t), val);
}

// These reads are proxied directly over to the device's PciConfig object so the validity of the
// widths and offsets will be validated on that end and then trickle back to this level of the
// protocol.
static zx_status_t pci_op_config_write(void* ctx, uint16_t offset, size_t width, uint32_t val) {
  kpci_device_t* dev = ctx;
  if (width > sizeof(uint32_t)) {
    return ZX_ERR_INVALID_ARGS;
  }

  pci_msg_t req = {
      .cfg =
          {
              .offset = offset,
              .width = (uint16_t)width,
              .value = val,
          },
  };
  pci_msg_t resp = {};
  return pci_rpc_request(dev, PCI_OP_CONFIG_WRITE, NULL, &req, &resp);
}

static zx_status_t pci_op_config_write8(void* ctx, uint16_t offset, uint8_t val) {
  return pci_op_config_write(ctx, offset, sizeof(uint8_t), val);
}

static zx_status_t pci_op_config_write16(void* ctx, uint16_t offset, uint16_t val) {
  return pci_op_config_write(ctx, offset, sizeof(uint16_t), val);
}

static zx_status_t pci_op_config_write32(void* ctx, uint16_t offset, uint32_t val) {
  return pci_op_config_write(ctx, offset, sizeof(uint32_t), val);
}

static zx_status_t pci_op_get_next_capability(void* ctx, uint8_t type, uint8_t in_offset,
                                              uint8_t* out_offset) {
  uint32_t cap_offset = 0;
  pci_op_config_read(ctx, in_offset + 1, sizeof(uint8_t), &cap_offset);
  uint8_t limit = 64;
  zx_status_t st;

  // Walk the capability list looking for the type requested, starting at the offset
  // passed in. limit acts as a barrier in case of an invalid capability pointer list
  // that causes us to iterate forever otherwise.
  while (cap_offset != 0 && limit--) {
    uint32_t type_id = 0;
    if ((st = pci_op_config_read(ctx, (uint16_t)cap_offset, sizeof(uint8_t), &type_id)) != ZX_OK) {
      zxlogf(ERROR, "%s: error reading type from cap offset %#x: %d", __func__, cap_offset, st);
      return st;
    }

    if (type_id == type) {
      *out_offset = (uint8_t)cap_offset;
      return ZX_OK;
    }

    // We didn't find the right type, move on, but ensure we're still
    // within the first 256 bytes of standard config space.
    if (cap_offset >= UINT8_MAX) {
      zxlogf(ERROR, "%s: %#x is an invalid capability offset!", __func__, cap_offset);
      return ZX_ERR_BAD_STATE;
    }
    if ((st = pci_op_config_read(ctx, (uint16_t)(cap_offset + 1), sizeof(uint8_t), &cap_offset)) !=
        ZX_OK) {
      zxlogf(ERROR, "%s: error reading next cap from cap offset %#x: %d", __func__, cap_offset + 1,
             st);
      return ZX_ERR_BAD_STATE;
    }
  }

  // No more entries are in the list
  return ZX_ERR_NOT_FOUND;
}

static zx_status_t pci_op_get_first_capability(void* ctx, uint8_t type, uint8_t* out_offset) {
  // the next_capability method will always look at the second byte next
  // pointer to fetch the next capability. By offsetting the CapPtr field
  // by -1 we can pretend we're working with a normal capability entry
  return pci_op_get_next_capability(ctx, type, PCI_CFG_CAPABILITIES_PTR - 1u, out_offset);
}

static zx_status_t pci_op_get_bar(void* ctx, uint32_t bar_id, zx_pci_bar_t* out_bar) {
  kpci_device_t* dev = ctx;
  pci_msg_t req = {
      .bar.id = bar_id,
  };
  pci_msg_t resp = {};
  zx_handle_t handle;
  zx_status_t st = pci_rpc_request(dev, PCI_OP_GET_BAR, &handle, &req, &resp);

  if (st == ZX_OK) {
    // Grab the payload and copy the handle over if one was passed back to us
    *out_bar = resp.bar;
    if (out_bar->type == ZX_PCI_BAR_TYPE_PIO) {
#if __x86_64__
      // x86 PIO space access requires permission in the I/O bitmap
      // TODO: this is the last remaining use of get_root_resource in pci
      // Please do not use get_root_resource() in new code. See fxbug.dev/31358.
      st =
          zx_ioports_request(get_root_resource(), (uint16_t)out_bar->addr, (uint16_t)out_bar->size);
      if (st != ZX_OK) {
        zxlogf(ERROR, "Failed to map IO window for bar into process: %d", st);
        return st;
      }
#else
      zxlogf(INFO,
             "%s: PIO bars may not be supported correctly on this arch. "
             "Please have someone check this!\n",
             __func__);
#endif
    } else {
      out_bar->handle = handle;
    }
  }
  return st;
}

static zx_status_t pci_op_map_interrupt(void* ctx, uint32_t which_irq, zx_handle_t* out_handle) {
  if (!out_handle) {
    return ZX_ERR_INVALID_ARGS;
  }

  kpci_device_t* dev = ctx;
  pci_msg_t req = {
      .irq.which_irq = which_irq,
  };
  pci_msg_t resp = {};
  zx_handle_t handle;
  zx_status_t st = pci_rpc_request(dev, PCI_OP_MAP_INTERRUPT, &handle, &req, &resp);
  if (st == ZX_OK) {
    *out_handle = handle;
  }
  return st;
}

static zx_status_t pci_op_get_bti(void* ctx, uint32_t index, zx_handle_t* out_handle) {
  if (!out_handle) {
    return ZX_ERR_INVALID_ARGS;
  }

  kpci_device_t* dev = ctx;
  pci_msg_t req = {.bti_index = index};
  pci_msg_t resp = {};
  zx_handle_t handle;
  zx_status_t st = pci_rpc_request(dev, PCI_OP_GET_BTI, &handle, &req, &resp);
  if (st == ZX_OK) {
    *out_handle = handle;
  }
  return st;
}

static zx_status_t pci_op_query_irq_mode(void* ctx, zx_pci_irq_mode_t mode,
                                         uint32_t* out_max_irqs) {
  kpci_device_t* dev = ctx;
  pci_msg_t req = {
      .irq.mode = mode,
  };
  pci_msg_t resp = {};
  zx_status_t st = pci_rpc_request(dev, PCI_OP_QUERY_IRQ_MODE, NULL, &req, &resp);
  if (st == ZX_OK) {
    *out_max_irqs = resp.irq.max_irqs;
  }
  return st;
}

static zx_status_t pci_op_set_irq_mode(void* ctx, zx_pci_irq_mode_t mode,
                                       uint32_t requested_irq_count) {
  kpci_device_t* dev = ctx;
  pci_msg_t req = {
      .irq =
          {
              .mode = mode,
              .requested_irqs = requested_irq_count,
          },
  };
  pci_msg_t resp = {};
  return pci_rpc_request(dev, PCI_OP_SET_IRQ_MODE, NULL, &req, &resp);
}

static zx_status_t pci_op_configure_irq_mode(void* ctx, uint32_t requested_irq_count) {
  kpci_device_t* dev = ctx;
  pci_msg_t req = {
      .irq =
          {
              .requested_irqs = requested_irq_count,
          },
  };
  pci_msg_t resp = {};
  return pci_rpc_request(dev, PCI_OP_CONFIGURE_IRQ_MODE, NULL, &req, &resp);
}

static zx_status_t pci_op_get_device_info(void* ctx, zx_pcie_device_info_t* out_info) {
  kpci_device_t* dev = ctx;
  pci_msg_t req = {};
  pci_msg_t resp = {};
  zx_status_t st = pci_rpc_request(dev, PCI_OP_GET_DEVICE_INFO, NULL, &req, &resp);
  if (st == ZX_OK) {
    *out_info = resp.info;
  }
  return st;
}

static pci_protocol_ops_t _pci_protocol = {
    .enable_bus_master = pci_op_enable_bus_master,
    .reset_device = pci_op_reset_device,
    .get_bar = pci_op_get_bar,
    .map_interrupt = pci_op_map_interrupt,
    .configure_irq_mode = pci_op_configure_irq_mode,
    .query_irq_mode = pci_op_query_irq_mode,
    .set_irq_mode = pci_op_set_irq_mode,
    .get_device_info = pci_op_get_device_info,
    .config_read8 = pci_op_config_read8,
    .config_read16 = pci_op_config_read16,
    .config_read32 = pci_op_config_read32,
    .config_write8 = pci_op_config_write8,
    .config_write16 = pci_op_config_write16,
    .config_write32 = pci_op_config_write32,
    .get_next_capability = pci_op_get_next_capability,
    .get_first_capability = pci_op_get_first_capability,
    .get_bti = pci_op_get_bti,
};

static zx_status_t pci_sysmem_connect(void* ctx, zx_handle_t handle) {
  kpci_device_t* dev = ctx;
  pci_msg_t req = {
      .handle = handle,
  };
  pci_msg_t resp = {};
  return pci_rpc_request(dev, PCI_OP_CONNECT_SYSMEM, NULL, &req, &resp);
};

static sysmem_protocol_ops_t sysmem_protocol = {
    .connect = pci_sysmem_connect,
};

static zx_status_t get_protocol(void* ctx, uint32_t proto_id, void* protocol) {
  if (proto_id == ZX_PROTOCOL_SYSMEM) {
    sysmem_protocol_t* proto = protocol;
    proto->ctx = ctx;
    proto->ops = &sysmem_protocol;
    return ZX_OK;
  } else if (proto_id == ZX_PROTOCOL_PCI) {
    pci_protocol_t* proto = protocol;
    proto->ctx = ctx;
    proto->ops = &_pci_protocol;
    return ZX_OK;
  }
  return ZX_ERR_NOT_SUPPORTED;
}

// A device ops structure appears to be required still, but does not need
// to have any of the methods implemented. All of the proxy's work is done
// in its protocol methods.
static zx_protocol_device_t device_ops = {
    .version = DEVICE_OPS_VERSION,
    .get_protocol = get_protocol,
};

static zx_status_t pci_proxy_create(void* ctx, zx_device_t* parent, const char* name,
                                    const char* args, zx_handle_t rpcch) {
  if (!parent || !args) {
    return ZX_ERR_BAD_STATE;
  }

  unsigned long index = strtoul(args, NULL, 10);
  zx_pcie_device_info_t info;
  kpci_device_t* device = calloc(1, sizeof(kpci_device_t));
  if (!device) {
    return ZX_ERR_NO_MEMORY;
  }

  if (index > UINT32_MAX) {
    return ZX_ERR_INVALID_ARGS;
  }

  // The channel and index are all we need to make this protocol call and the
  // upper devhost is already fully initialized at this point so we can get
  // our bind information from it.
  device->index = (uint32_t)index;
  device->pciroot_rpcch = rpcch;
  zx_status_t st = pci_op_get_device_info(device, &info);
  if (st != ZX_OK) {
    free(device);
    return st;
  }

  char devname[20];
  snprintf(devname, sizeof(devname), "%02x:%02x.%1x", info.bus_id, info.dev_id, info.func_id);
  device_add_args_t device_args = {
      .version = DEVICE_ADD_ARGS_VERSION,
      .name = devname,
      .ctx = device,
      .ops = &device_ops,
      .proto_id = ZX_PROTOCOL_PCI,
      .proto_ops = &_pci_protocol,
  };

  st = device_add(parent, &device_args, &device->zxdev);
  if (st != ZX_OK) {
    free(device);
  }
  return st;
}

static zx_driver_ops_t kpci_driver_ops = {
    .version = DRIVER_OPS_VERSION,
    .create = pci_proxy_create,
};

// clang-format off
ZIRCON_DRIVER_BEGIN(pci_proxy, kpci_driver_ops, "zircon", "0.1", 1)
    BI_ABORT_IF_AUTOBIND,
ZIRCON_DRIVER_END(pci_proxy)
    // clang-format on
