// Copyright 2016 The Fuchsia Authors
// Copyright (c) 2016, Google, Inc. All rights reserved
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <assert.h>
#include <debug.h>
#include <string.h>
#include <trace.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <dev/pci_config.h>
#include <dev/pcie_device.h>
#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <ktl/iterator.h>

#define LOCAL_TRACE 0

/*
 * TODO(cja) Re-add the paranoid sanity checks on capability placement
 * and size that was in the old code. Doing this sanely likely involves keeping
 * the various C style structures for the capabilities in pcie_caps.h originally
 */

static bool quirk_should_force_pcie(const PcieDevice& dev) {
  static const struct {
    uint16_t vendor_id;
    uint16_t device_id;
  } QUIRK_LIST[] = {
      {.vendor_id = 0x8086, .device_id = 0x1616},  // Wildcat Point GPU
  };

  for (size_t i = 0; i < ktl::size(QUIRK_LIST); ++i) {
    if ((QUIRK_LIST[i].vendor_id == dev.vendor_id()) &&
        (QUIRK_LIST[i].device_id == dev.device_id()))
      return true;
  }

  return false;
}

/*
 * Advanced Capabilities for Conventional PCI ECN
 */
PciCapAdvFeatures::PciCapAdvFeatures(const PcieDevice& dev, uint16_t base, uint8_t id)
    : PciStdCapability(dev, base, id) {
  DEBUG_ASSERT(id == PCIE_CAP_ID_ADVANCED_FEATURES);
  auto cfg = dev.config();

  length_ = PciReg8(static_cast<uint16_t>(base_ + kLengthOffset));
  af_caps_ = PciReg8(static_cast<uint16_t>(base_ + kAFCapsOffset));
  af_ctrl_ = PciReg8(static_cast<uint16_t>(base_ + kAFControlOffset));
  af_status_ = PciReg8(static_cast<uint16_t>(base_ + kAFStatusOffset));

  uint8_t caps = cfg->Read(af_caps_);
  has_flr_ = PCS_ADVCAPS_CAP_HAS_FUNC_LEVEL_RESET(caps);
  has_tp_ = PCS_ADVCAPS_CAP_HAS_TRANS_PENDING(caps);

  uint8_t length = cfg->Read(length_);
  if (length != PCS_ADVCAPS_LENGTH) {
    TRACEF("Length of %u does not match the spec length of %u!\n", length, PCS_ADVCAPS_LENGTH);
    return;
  }

  is_valid_ = true;
}

/*
 * PCI Express Base Specification 1.1  Section 7.8 (version 1)
 * PCI Express Base Specification 3.1a Section 7.8 (version 2)
 */
PciCapPcie::PciCapPcie(const PcieDevice& dev, uint16_t base, uint8_t id)
    : PciStdCapability(dev, base, id) {
  DEBUG_ASSERT(id == PCIE_CAP_ID_PCI_EXPRESS);
  auto cfg = dev.config();

  /* Have we already initialized PCIE? */
  if (is_valid_) {
    TRACEF(
        "Device %02x:%02x.%01x (%04hx:%04hx) has more than one PCI "
        "Express capability structure!\n",
        dev.bus_id(), dev.dev_id(), dev.func_id(), dev.vendor_id(), dev.device_id());
    return;
  }

  caps_ = PciReg16(static_cast<uint16_t>(base_ + kPcieCapsOffset));
  auto cap_val = cfg->Read(caps_);
  version_ = PCS_CAPS_VERSION(cap_val);
  devtype_ = PCS_CAPS_DEVTYPE(cap_val);

  /*
   * Set up all the offsets for the various chunks in the device. Some may
   * not be supported, but regardless of whether they are there the final
   * structure will be the same.
   */
  device.caps_ = PciReg32(static_cast<uint16_t>(base_ + kCapsOffset(kDeviceOffset)));
  device.ctrl_ = PciReg16(static_cast<uint16_t>(base_ + kControlOffset(kDeviceOffset)));
  device.status_ = PciReg16(static_cast<uint16_t>(base_ + kStatusOffset(kDeviceOffset)));

  link.caps_ = PciReg32(static_cast<uint16_t>(base_ + kCapsOffset(kLinkOffset)));
  link.ctrl_ = PciReg16(static_cast<uint16_t>(base_ + kControlOffset(kLinkOffset)));
  link.status_ = PciReg16(static_cast<uint16_t>(base_ + kStatusOffset(kLinkOffset)));

  slot.caps_ = PciReg32(static_cast<uint16_t>(base_ + kCapsOffset(kSlotOffset)));
  slot.ctrl_ = PciReg16(static_cast<uint16_t>(base_ + kControlOffset(kSlotOffset)));
  slot.status_ = PciReg16(static_cast<uint16_t>(base_ + kStatusOffset(kSlotOffset)));

  root.caps_ = PciReg16(static_cast<uint16_t>(base_ + kRootCapsOffset));
  root.ctrl_ = PciReg16(static_cast<uint16_t>(base_ + kRootControlOffset));
  root.status_ = PciReg32(static_cast<uint16_t>(base_ + kRootStatusOffset));

  device2.caps_ = PciReg32(static_cast<uint16_t>(base_ + kCapsOffset(kDevice2Offset)));
  device2.ctrl_ = PciReg16(static_cast<uint16_t>(base_ + kControlOffset(kDevice2Offset)));
  device2.status_ = PciReg16(static_cast<uint16_t>(base_ + kStatusOffset(kDevice2Offset)));

  link2.caps_ = PciReg32(static_cast<uint16_t>(base_ + kCapsOffset(kLinkOffset)));
  link2.ctrl_ = PciReg16(static_cast<uint16_t>(base_ + kControlOffset(kLinkOffset)));
  link2.status_ = PciReg16(static_cast<uint16_t>(base_ + kStatusOffset(kLinkOffset)));

  slot2.caps_ = PciReg32(static_cast<uint16_t>(base_ + kCapsOffset(kSlotOffset)));
  slot2.ctrl_ = PciReg16(static_cast<uint16_t>(base_ + kControlOffset(kSlotOffset)));
  slot2.status_ = PciReg16(static_cast<uint16_t>(base_ + kStatusOffset(kSlotOffset)));

  /* Sanity check the device/port type */
  switch (devtype_) {
    // Type 0 config header types
    case PCIE_DEVTYPE_PCIE_ENDPOINT:
    case PCIE_DEVTYPE_LEGACY_PCIE_ENDPOINT:
    case PCIE_DEVTYPE_RC_INTEGRATED_ENDPOINT:
    case PCIE_DEVTYPE_RC_EVENT_COLLECTOR:
      if (dev.is_bridge()) {
        TRACEF(
            "Device %02x:%02x.%01x (%04hx:%04hx) has a Type 0 PCIe "
            "device type (0x%x) in PCIe capabilities structure, but "
            "does not have a Type 0 config header.\n",
            dev.bus_id(), dev.dev_id(), dev.func_id(), dev.vendor_id(), dev.device_id(), devtype_);
        return;
      }
      break;

    // Type 1 config header types
    case PCIE_DEVTYPE_RC_ROOT_PORT:
    case PCIE_DEVTYPE_SWITCH_UPSTREAM_PORT:
    case PCIE_DEVTYPE_SWITCH_DOWNSTREAM_PORT:
    case PCIE_DEVTYPE_PCIE_TO_PCI_BRIDGE:
    case PCIE_DEVTYPE_PCI_TO_PCIE_BRIDGE:
      if (!dev.is_bridge()) {
        TRACEF(
            "Device %02x:%02x.%01x (%04hx:%04hx) has a Type 1 PCIe "
            "device type (0x%x) in PCIe capabilities structure, but "
            "does not have a Type 1 config header.\n",
            dev.bus_id(), dev.dev_id(), dev.func_id(), dev.vendor_id(), dev.device_id(), devtype_);
        return;
      }
      break;

    default:
      TRACEF(
          "Device %02x:%02x.%01x (%04hx:%04hx) has an illegal PCIe "
          "device type (0x%x) in PCIe capabilities structure.\n",
          dev.bus_id(), dev.dev_id(), dev.func_id(), dev.vendor_id(), dev.device_id(), devtype_);
      return;
  }

  /* TODO(johngro): remember to read the MSI/MSI-X interrupt message number
   * field when setting up for MSI/MSI-X.  We almost certainly need to hook
   * this IRQ in order to be aware of any changes to the extended
   * capabilities.  It is unclear whether or not we should allow this IRQ to
   * be passed thru to the device driver or not.
   */

  /* Check device capabilities to see if we support function level reset or
   * not */
  uint32_t devcaps = cfg->Read(device.caps());
  has_flr_ = (PCS_DEV_CAPS_FUNC_LEVEL_RESET(devcaps) != 0);

  is_valid_ = true;
}

/*
 * @see PCI Local Bus Specification 3.0 Section 6.8.1
 */
PciCapMsi::PciCapMsi(const PcieDevice& dev, uint16_t base, uint8_t id)
    : PciStdCapability(dev, base, id) {
  DEBUG_ASSERT(id == PCIE_CAP_ID_MSI);
  auto cfg = dev.config();

  // Set up the rest of the registers based on whether we're 64 bit or not.
  ctrl_ = PciReg16(static_cast<uint16_t>(base_ + kControlOffset));
  addr_ = PciReg32(static_cast<uint16_t>(base_ + kAddrOffset));

  uint16_t ctrl = cfg->Read(ctrl_reg());
  has_pvm_ = PCIE_CAP_MSI_CTRL_PVM_SUPPORTED(ctrl);
  is_64_bit_ = PCIE_CAP_MSI_CTRL_64BIT_SUPPORTED(ctrl);
  msi_size_ = (has_pvm_ ? (is_64_bit_ ? k64BitPvmSize : k32BitPvmSize)
                        : (is_64_bit_ ? k64BitNoPvmSize : k32BitNoPvmSize));

  if (is_64_bit_) {
    addr_upper_ = PciReg32(static_cast<uint16_t>(base_ + kAddrUpperOffset));
    data_ = PciReg16(static_cast<uint16_t>(base_ + kData64Offset));
    mask_bits_ = PciReg32(static_cast<uint16_t>(base_ + kMaskBits64Offset));
    pending_bits_ = PciReg32(static_cast<uint16_t>(base_ + kPendingBits64Offset));
  } else {
    data_ = PciReg16(static_cast<uint16_t>(base_ + kData32Offset));
    mask_bits_ = PciReg32(static_cast<uint16_t>(base_ + kMaskBits32Offset));
    pending_bits_ = PciReg32(static_cast<uint16_t>(base_ + kPendingBits32Offset));
  }

  memset(&irq_block_, 0, sizeof(irq_block_));
  uint16_t msi_end = static_cast<uint16_t>(base_ + msi_size_);
  uint16_t cfgend = PCIE_BASE_CONFIG_SIZE;

  if (msi_end >= cfgend) {
    TRACEF(
        "Device %02x:%02x.%01x (%04hx:%04hx) has illegally positioned MSI "
        "capability structure.  Structure %s 64-bit addressing and %s "
        "per-vector masking and should be %u bytes long, but the "
        "structure ends at %u, %u bytes past the end of config "
        "space\n",
        dev.bus_id(), dev.dev_id(), dev.func_id(), dev.vendor_id(), dev.device_id(),
        is_64_bit_ ? "supports" : "does not support", has_pvm_ ? "supports" : "does not support",
        msi_size_, msi_end, static_cast<unsigned int>(cfgend - msi_end));
    return;
  }

  /* Sanity check the Multi-Message Capable field */
  max_irqs_ = 0x1u << PCIE_CAP_MSI_CTRL_GET_MMC(ctrl);
  if (max_irqs_ > PCIE_MAX_MSI_IRQS) {
    TRACEF(
        "Device %02x:%02x.%01x (%04hx:%04hx) has invalid Multi-Message "
        "Capable value in MSI capability structure (%d).  Structure "
        "claims to support %u vectors, but %u is the maximum allowed.\n",
        dev.bus_id(), dev.dev_id(), dev.func_id(), dev.vendor_id(), dev.device_id(),
        PCIE_CAP_MSI_CTRL_GET_MMC(ctrl), max_irqs_, PCIE_MAX_MSI_IRQS);
    return;
  }

  /* Success!
   *
   * Make sure that MSI is disabled and that the Multi-Message Enable field is
   * set to 1-vector (multi-message disabled).  Then record our capabilities
   * in the device's bookkeeping and we are done.
   */
  cfg->Write(ctrl_reg(), PCIE_CAP_MSI_CTRL_SET_MME(0, PCIE_CAP_MSI_CTRL_SET_ENB(0, ctrl)));
  if (has_pvm_)
    cfg->Write(mask_bits_reg(), 0xFFFFFFFF);

  is_valid_ = true;
}

/* Catch quirks and invalid capability offsets we may see */
inline zx_status_t validate_capability_offset(uint8_t offset) {
  if (offset == 0xFF || offset < PCIE_CAP_PTR_MIN_VALID || offset > PCIE_CAP_PTR_MAX_VALID) {
    return ZX_ERR_INVALID_ARGS;
  }

  return ZX_OK;
}

/*
 * TODO(cja): It may be worth moving to table based solution like we had before
 * where we have a single parse function and a function table for it to use,
 * but it involves a bit more worrying about ownership of capabilities and
 * std / ext attributes.
 */

zx_status_t PcieDevice::ParseStdCapabilitiesLocked() {
  zx_status_t res = ZX_OK;
  uint8_t cap_offset = cfg_->Read(PciConfig::kCapabilitiesPtr);
  uint8_t caps_found = 0;
  fbl::AllocChecker ac;

  /*
   * Walk the pointer list for the standard capabilities table. As a safety,
   * keep track of how many capabilities we've looked at to prevent potential
   * cycles from walking forever. Any supported capability will be parsed
   * by their object in the PcieDevice, and are additionally stored in a list
   * for reference later.
   */
  LTRACEF("Scanning for capabilities at %02x:%02x.%01x (%04hx:%04hx)\n", bus_id(), dev_id(),
          func_id(), vendor_id(), device_id());
  while (cap_offset != PCIE_CAP_PTR_NULL && caps_found < PCIE_MAX_CAPABILITIES) {
    if ((res = validate_capability_offset(cap_offset)) != ZX_OK) {
      TRACEF("Device %02x:%02x.%01x (%04hx:%04hx) has invalid cptr (%#02x)\n", bus_id(), dev_id(),
             func_id(), vendor_id(), device_id(), cap_offset);
      break;
    }

    uint8_t id = cfg_->Read(PciReg8(cap_offset));

    LTRACEF("Found capability (#%u, id = 0x%02x) for device %02x:%02x.%01x (%04hx:%04hx)\n",
            caps_found, id, bus_id(), dev_id(), func_id(), vendor_id(), device_id());
    /*
     * Depending on the capability found we allocate a structure of the appropriate type
     * and add it to the bookkeeping tree. For important things like MSI/PCIE we cache a raw
     * pointer to it for fast access, but otherwise everything is found via the capability list.
     *
     * TODO(cja): if we make this a two stage allocation/initialization in the future we can do
     * away with is_valid() style checks that are done in additional checking if pcie_/msi_ are
     * valid pointers.
     */
    PciStdCapability* cap;
    switch (id) {
      case PCIE_CAP_ID_MSI:
        cap = irq_.msi = new (&ac) PciCapMsi(*this, cap_offset, id);
        break;
      case PCIE_CAP_ID_PCI_EXPRESS:
        cap = pcie_ = new (&ac) PciCapPcie(*this, cap_offset, id);
        break;
      case PCIE_CAP_ID_ADVANCED_FEATURES:
        cap = pci_af_ = new (&ac) PciCapAdvFeatures(*this, cap_offset, id);
        break;

      default:
        cap = new (&ac) PciStdCapability(*this, cap_offset, id);
        break;
    }

    if (!ac.check()) {
      TRACEF("Could not allocate memory fori capability 0x%02x\n", id);
      return ZX_ERR_NO_MEMORY;
    }

    caps_.detected.push_front(ktl::unique_ptr<PciStdCapability>(cap));
    cap_offset = cfg_->Read(PciReg8(static_cast<uint16_t>(cap_offset + 0x1))) & 0xFC;
    caps_found++;
  }

  return res;
}

zx_status_t PcieDevice::ParseExtCapabilitiesLocked() {
  /*
   * TODO(cja): Since ExtCaps are a no-op right now (we had nothing in the table for
   * supported extended capabilities) this is a stub for now.
   */
  return ZX_OK;
}

// Parse PCI Standard Capabilities starting with the pointer in the PCI
// config structure.
zx_status_t PcieDevice::ProbeCapabilitiesLocked() {
  zx_status_t ret = ParseStdCapabilitiesLocked();
  if (ret != ZX_OK) {
    return ret;
  }

  /* If this device is PCIe device, the parse the extended configuration
   * section of the PCI config looking for extended capabilities.  Based on
   * the spec, we should only need to look for a PCI Express Capability
   * Structure in the standard config section to make the determination that
   * this device is a legit PCIe device.
   *
   * This said, I have encountered at least one device (the graphics
   * controller in the Wildcat Point PCH) which clearly is PCIe and clearly
   * has extended capabilities, but which is not spec compliant and does not
   * contain a proper PCI Express Capability Structure.  Because of this, we
   * maintain a quirks list of non compliant devices which are actually PCIe,
   * but do not appear to be so at first glance. */
  if ((is_pcie() || quirk_should_force_pcie(*this)) && pcie_->is_valid()) {
    ret = ParseExtCapabilitiesLocked();
  }

  return ret;
}
