// Copyright 2020 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 <fuchsia/hardware/pci/c/banjo.h>
#include <fuchsia/hardware/pci/cpp/banjo.h>
#include <lib/mmio/mmio.h>
#include <lib/zx/status.h>
#include <zircon/assert.h>
#include <zircon/errors.h>
#include <zircon/status.h>

#include <fbl/algorithm.h>
#include <fbl/string_buffer.h>
#include <fbl/string_printf.h>

#include "src/devices/bus/drivers/pci/capabilities/msi.h"
#include "src/devices/bus/drivers/pci/common.h"
#include "src/devices/bus/drivers/pci/device.h"

namespace pci {

zx::status<uint32_t> Device::QueryIrqMode(pci_irq_mode_t mode) {
  fbl::AutoLock dev_lock(&dev_lock_);
  switch (mode) {
    case PCI_IRQ_MODE_LEGACY:
    case PCI_IRQ_MODE_LEGACY_NOACK:
      if (cfg_->Read(Config::kInterruptLine) != 0) {
        return zx::ok(PCI_LEGACY_INT_COUNT);
      }
      break;
    case PCI_IRQ_MODE_MSI:
      if (caps_.msi) {
        return zx::ok(caps_.msi->vectors_avail());
      }
      break;
    case PCI_IRQ_MODE_MSI_X:
      if (caps_.msix) {
        return zx::ok(caps_.msix->table_size());
      }
      break;
    case PCI_IRQ_MODE_DISABLED:
    default:
      return zx::error(ZX_ERR_INVALID_ARGS);
  }
  return zx::error(ZX_ERR_NOT_SUPPORTED);
}

zx_status_t Device::SetIrqMode(pci_irq_mode_t mode, uint32_t irq_cnt) {
  if (mode >= PCI_IRQ_MODE_COUNT) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  if (mode != PCI_IRQ_MODE_DISABLED && irq_cnt == 0) {
    return ZX_ERR_INVALID_ARGS;
  }

  fbl::AutoLock dev_lock(&dev_lock_);
  // Before enabling any given interrupt mode we need to ensure no existing
  // interrupts are configured. Disabling them can fail in cases downstream
  // drivers have mot freed outstanding interrupt objects allocated off of
  // an MSI object.
  if (zx_status_t st = DisableInterrupts(); st != ZX_OK) {
    return st;
  }

  // At this point interrupts have been disabled, so we're already successful
  // if that was the intent.
  if (mode == PCI_IRQ_MODE_DISABLED) {
    return ZX_OK;
  }

  switch (mode) {
    case PCI_IRQ_MODE_LEGACY:
      return EnableLegacy(/*needs_ack=*/true);
    case PCI_IRQ_MODE_LEGACY_NOACK:
      return EnableLegacy(/*needs_ack=*/false);
    case PCI_IRQ_MODE_MSI:
      if (caps_.msi) {
        return EnableMsi(irq_cnt);
      }
      break;
    case PCI_IRQ_MODE_MSI_X:
      if (caps_.msix) {
        return EnableMsix(irq_cnt);
      }
      break;
  }
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t Device::DisableInterrupts() {
  zx_status_t st = ZX_OK;
  switch (irqs_.mode) {
    case PCI_IRQ_MODE_DISABLED:
      return ZX_OK;
    case PCI_IRQ_MODE_LEGACY:
    case PCI_IRQ_MODE_LEGACY_NOACK:
      st = DisableLegacy();
      break;
    case PCI_IRQ_MODE_MSI:
      st = DisableMsi();
      break;
    case PCI_IRQ_MODE_MSI_X:
      st = DisableMsix();
      break;
  }

  if (st == ZX_OK) {
    zxlogf(DEBUG, "[%s] disabled IRQ mode %u", cfg_->addr(), irqs_.mode);
    irqs_.mode = PCI_IRQ_MODE_DISABLED;
    metrics_.irq_mode.Set(kInspectIrqModes[irqs_.mode]);
  }
  return st;
}

zx::status<zx::interrupt> Device::MapInterrupt(uint32_t which_irq) {
  fbl::AutoLock dev_lock(&dev_lock_);
  // MSI support is controlled through the capability held within the device's configuration space,
  // so the dispatcher needs acess to the given device's config vmo. MSI-X needs access to the table
  // structure which is held in one of the device BARs, but a view is built ahead of time for it
  // when the MSI-X capability is initialized.
  if (irqs_.mode == PCI_IRQ_MODE_DISABLED) {
    return zx::error(ZX_ERR_BAD_STATE);
  }

  zx::interrupt interrupt = {};
  zx_status_t status = ZX_OK;
  switch (irqs_.mode) {
    case PCI_IRQ_MODE_LEGACY:
    case PCI_IRQ_MODE_LEGACY_NOACK: {
      if (which_irq != 0) {
        return zx::error(ZX_ERR_INVALID_ARGS);
      }
      status = irqs_.legacy.duplicate(ZX_RIGHT_SAME_RIGHTS, &interrupt);
      break;
    }
    case PCI_IRQ_MODE_MSI: {
      zx::status<ddk::MmioView> view_res = cfg_->get_view();
      if (!view_res.is_ok()) {
        return view_res.take_error();
      }

      status = zx::msi::create(irqs_.msi_allocation, /*options=*/0, which_irq, *view_res->get_vmo(),
                               view_res->get_offset() + caps_.msi->base(), &interrupt);
      break;
    }
    case PCI_IRQ_MODE_MSI_X: {
      auto& msix = caps_.msix;
      status = zx::msi::create(irqs_.msi_allocation, ZX_MSI_MODE_MSI_X, which_irq,
                               *msix->table_vmo(), msix->table_offset(), &interrupt);
      // Disable the function level masking now that at least one interrupt exists for the device.
      if (status == ZX_OK) {
        MsixControlReg ctrl = {.value = cfg_->Read(caps_.msix->ctrl())};
        ctrl.set_function_mask(0);
        cfg_->Write(caps_.msix->ctrl(), ctrl.value);
      }
      break;
    }
    default:
      return zx::error(ZX_ERR_BAD_STATE);
  }

  if (status != ZX_OK) {
    return zx::error(status);
  }

  return zx::ok(std::move(interrupt));
}

zx_status_t Device::SignalLegacyIrq(zx_time_t timestamp) const {
  metrics_.legacy.signal_count.Add(1);
  return irqs_.legacy.trigger(/*options=*/0, zx::time(timestamp));
}

zx_status_t Device::AckLegacyIrq() {
  if (irqs_.mode != PCI_IRQ_MODE_LEGACY) {
    return ZX_ERR_BAD_STATE;
  }

  EnableLegacyIrq();
  metrics_.legacy.ack_count.Add(1);
  return ZX_OK;
}

void Device::EnableLegacyIrq() {
  ModifyCmdLocked(/*clr_bits=*/PCI_CFG_COMMAND_INT_DISABLE, /*set_bits=*/0);
  irqs_.legacy_disabled = false;
  metrics_.legacy.disabled.Set(irqs_.legacy_disabled);
}

void Device::DisableLegacyIrq() {
  ModifyCmdLocked(/*clr_bits=*/0, /*set_bits=*/PCI_CFG_COMMAND_INT_DISABLE);
  irqs_.legacy_disabled = true;
  metrics_.legacy.disabled.Set(irqs_.legacy_disabled);
}

zx::status<std::pair<zx::msi, zx_info_msi_t>> Device::AllocateMsi(uint32_t irq_cnt) {
  zx::msi msi;
  zx_status_t st = bdi_->AllocateMsi(irq_cnt, &msi);
  if (st != ZX_OK) {
    return zx::error(st);
  }

  zx_info_msi_t msi_info;
  st = msi.get_info(ZX_INFO_MSI, &msi_info, sizeof(msi_info), nullptr, nullptr);
  if (st != ZX_OK) {
    return zx::error(st);
  }
  ZX_DEBUG_ASSERT(msi_info.num_irq == irq_cnt);
  ZX_DEBUG_ASSERT(msi_info.interrupt_count == 0);

  metrics_.msi.allocated.Set(msi_info.num_irq);
  metrics_.msi.base_vector.Set(msi_info.base_irq_id);
  return zx::ok(std::make_pair(std::move(msi), msi_info));
}

zx_status_t Device::EnableLegacy(bool needs_ack) {
  irqs_.legacy_vector = cfg_->Read(Config::kInterruptLine);
  if (irqs_.legacy_vector == 0) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  zx_status_t status = bdi_->AddToSharedIrqList(this, irqs_.legacy_vector);
  if (status != ZX_OK) {
    zxlogf(ERROR, "[%s] failed to add legacy irq to shared handler list %#x: %s", cfg_->addr(),
           irqs_.legacy_vector, zx_status_get_string(status));
    return status;
  }

  ModifyCmdLocked(/*clr_bits=*/PCIE_CFG_COMMAND_INT_DISABLE, /*set_bits=*/0);
  irqs_.mode = (needs_ack) ? PCI_IRQ_MODE_LEGACY : PCI_IRQ_MODE_LEGACY_NOACK;
  metrics_.irq_mode.Set(kInspectIrqModes[irqs_.mode]);
  return ZX_OK;
}

zx_status_t Device::EnableMsi(uint32_t irq_cnt) {
  ZX_DEBUG_ASSERT(irqs_.mode == PCI_IRQ_MODE_DISABLED);
  ZX_DEBUG_ASSERT(!irqs_.msi_allocation);
  ZX_DEBUG_ASSERT(caps_.msi);

  if (!fbl::is_pow2(irq_cnt) || irq_cnt > caps_.msi->vectors_avail()) {
    zxlogf(DEBUG, "[%s] EnableMsi: bad irq count = %u, available = %u\n", cfg_->addr(), irq_cnt,
           caps_.msi->vectors_avail());
    return ZX_ERR_INVALID_ARGS;
  }

  // Bus mastering must be enabled to generate MSI messages.
  zx_status_t status = EnableBusMaster(true);
  if (status != ZX_OK) {
    zxlogf(ERROR, "[%s] Failed to enable bus mastering for MSI mode (%d)", cfg_->addr(), status);
    return status;
  }

  auto result = AllocateMsi(irq_cnt);
  if (result.is_ok()) {
    auto [alloc, info] = std::move(result.value());
    MsiControlReg ctrl = {.value = cfg_->Read(caps_.msi->ctrl())};
    cfg_->Write(caps_.msi->tgt_addr(), info.target_addr);
    cfg_->Write(caps_.msi->tgt_data(), info.target_data);
    if (ctrl.mm_capable()) {
      ctrl.set_mm_enable(MsiCapability::CountToMmc(irq_cnt));
    }
    ctrl.set_enable(1);
    cfg_->Write(caps_.msi->ctrl(), ctrl.value);

    irqs_.msi_allocation = std::move(alloc);
    irqs_.mode = PCI_IRQ_MODE_MSI;
    metrics_.irq_mode.Set(kInspectIrqModes[irqs_.mode]);
  }
  return result.status_value();
}

zx_status_t Device::EnableMsix(uint32_t irq_cnt) {
  ZX_DEBUG_ASSERT(irqs_.mode == PCI_IRQ_MODE_DISABLED);
  ZX_DEBUG_ASSERT(!irqs_.msi_allocation);
  ZX_DEBUG_ASSERT(caps_.msix);

  // Bus mastering must be enabled to generate MSI-X messages.
  zx_status_t status = EnableBusMaster(true);
  if (status != ZX_OK) {
    zxlogf(ERROR, "[%s] Failed to enable bus mastering for MSI-X mode (%d)", cfg_->addr(), status);
    return status;
  }

  // MSI-X supports non-pow2 counts, but the MSI allocator still allocates in
  // pow2 based blocks.
  uint32_t irq_cnt_pow2 = fbl::roundup_pow2(irq_cnt);
  auto result = AllocateMsi(irq_cnt_pow2);
  if (result.is_ok()) {
    auto [alloc, info] = std::move(result.value());
    // Enable MSI-X, but mask off all functions until an interrupt is mapped.
    MsixControlReg ctrl = {.value = cfg_->Read(caps_.msix->ctrl())};
    ctrl.set_function_mask(1);
    ctrl.set_enable(1);
    cfg_->Write(caps_.msix->ctrl(), ctrl.value);

    irqs_.msi_allocation = std::move(alloc);
    irqs_.mode = PCI_IRQ_MODE_MSI_X;
    metrics_.irq_mode.Set(kInspectIrqModes[PCI_IRQ_MODE_MSI_X]);
  }
  return result.status_value();
}

zx_status_t Device::DisableLegacy() {
  zx_status_t status = bdi_->RemoveFromSharedIrqList(this, irqs_.legacy_vector);
  if (status != ZX_OK) {
    zxlogf(ERROR, "[%s] failed to remove legacy irq to shared handler list %#x: %s", cfg_->addr(),
           irqs_.legacy_vector, zx_status_get_string(status));
    return status;
  }

  ModifyCmdLocked(/*clr_bits=*/0, /*set_bits=*/PCIE_CFG_COMMAND_INT_DISABLE);
  irqs_.legacy_vector = 0;
  return ZX_OK;
}

// In general, if a device driver tries to disable an interrupt mode while
// holding handles to individual interrupts then it's considered a bad state.
// TODO(fxbug.dev/32978): Are there cases where the bus driver would want to hard disable
// IRQs even though the driver holds outstanding handles? In the event of a driver
// crash the handles will be released, but in a hard disable path they would still
// exist.
zx_status_t Device::VerifyAllMsisFreed() {
  if (!irqs_.msi_allocation) {
    return ZX_OK;
  }

  zx_info_msi_t info = {};
  zx_status_t st =
      irqs_.msi_allocation.get_info(ZX_INFO_MSI, &info, sizeof(info), nullptr, nullptr);
  if (st != ZX_OK) {
    return st;
  }

  if (info.interrupt_count != 0) {
    return ZX_ERR_BAD_STATE;
  }

  return ZX_OK;
}

void Device::DisableMsiCommon() {
  irqs_.msi_allocation.reset();
  metrics_.msi.allocated.Set(0);
  metrics_.msi.base_vector.Set(0);
}

zx_status_t Device::DisableMsi() {
  ZX_DEBUG_ASSERT(caps_.msi);
  if (zx_status_t st = VerifyAllMsisFreed(); st != ZX_OK) {
    return st;
  }

  MsiControlReg ctrl = {.value = cfg_->Read(caps_.msi->ctrl())};
  ctrl.set_enable(0);
  cfg_->Write(caps_.msi->ctrl(), ctrl.value);

  DisableMsiCommon();
  return ZX_OK;
}

zx_status_t Device::DisableMsix() {
  ZX_DEBUG_ASSERT(caps_.msix);
  if (zx_status_t st = VerifyAllMsisFreed(); st != ZX_OK) {
    return st;
  }

  MsixControlReg ctrl = {.value = cfg_->Read(caps_.msix->ctrl())};
  ctrl.set_function_mask(1);
  ctrl.set_enable(0);
  cfg_->Write(caps_.msix->ctrl(), ctrl.value);

  irqs_.msi_allocation.reset();
  return ZX_OK;
}

}  // namespace pci
