// Copyright 2019 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.
#ifndef SRC_DEVICES_BUS_DRIVERS_PCI_CAPABILITIES_MSIX_H_
#define SRC_DEVICES_BUS_DRIVERS_PCI_CAPABILITIES_MSIX_H_

#include <lib/mmio/mmio.h>
#include <lib/zx/vmo.h>

#include <algorithm>

#include <hwreg/bitfields.h>

#include "../bar_info.h"
#include "../capabilities.h"
#include "../common.h"

namespace pci {

struct MsixControlReg {
  uint16_t value;
  DEF_SUBBIT(value, 15, enable);
  DEF_SUBBIT(value, 14, function_mask);
  DEF_SUBFIELD(value, 10, 0, table_size);
};

struct MsixTableReg : hwreg::RegisterBase<MsixTableReg, uint32_t> {
  DEF_UNSHIFTED_FIELD(31, 3, offset);
  DEF_FIELD(2, 0, bir);

  static auto Get() { return hwreg::RegisterAddr<MsixTableReg>(0); }
};

struct MsixPbaReg : hwreg::RegisterBase<MsixPbaReg, uint32_t> {
  DEF_UNSHIFTED_FIELD(31, 3, offset);
  DEF_FIELD(2, 0, bir);

  static auto Get() { return hwreg::RegisterAddr<MsixPbaReg>(0); }
};

struct MsixTable {
  uint32_t msg_addr;
  uint32_t msg_upper_addr;
  uint32_t msg_data;
  uint32_t vector_ctrl;
};
static_assert(sizeof(MsixTable) == 16);

// PCI Local Bus Spec 6.8.2: MSI-X Capability and Table Structure.
class MsixCapability : public Capability {
 public:
  MsixCapability(const Config& cfg, uint8_t base)
      : Capability(static_cast<uint8_t>(Capability::Id::kMsiX), base, cfg.addr()),
        ctrl_(PciReg16(static_cast<uint16_t>(base + 0x2))),
        table_reg_(PciReg32(static_cast<uint16_t>(base + 0x4))),
        pba_reg_(PciReg32(static_cast<uint16_t>(base + 0x8))) {
    MsixControlReg ctrl = {.value = cfg.Read(ctrl_)};
    // Table size is stored in the register as N-1 (PCIe Base Spec 7.7.2.2)
    table_size_ = static_cast<uint16_t>(ctrl.table_size() + 1);

    // Offset assumes a full 32bit width and is handled by the unshifted
    // field in the register structures.
    auto table = MsixTableReg::Get().FromValue(cfg.Read(table_reg_));
    table_bar_ = static_cast<uint8_t>(table.bir());
    table_offset_ = table.offset();

    auto pba = MsixPbaReg::Get().FromValue(cfg.Read(pba_reg_));
    pba_bar_ = static_cast<uint8_t>(pba.bir());
    pba_offset_ = pba.offset();
  }

  zx_status_t Init(const Bar& tbar, const Bar& pbar) {
    if (inited_) {
      return ZX_ERR_BAD_STATE;
    }

    // Every vector has one entry in the table and in the pending bit array.
    size_t tbl_bytes = table_size_ * sizeof(MsixTable);
    // Every vector has a single bit in a large contiguous bitmask.
    // where the smallest allocation is 64 bits.
    size_t pba_bytes = ((table_size_ / 64) + 1) * sizeof(uint64_t);
    zxlogf(TRACE, "[%s] MSI-X supports %u vector%c", addr(), table_size_,
           (table_size_ == 1) ? ' ' : 's');
    zxlogf(TRACE, "[%s] MSI-X mask table bar %u @ %#x-%#zx", addr(), table_bar_, table_offset_,
           table_offset_ + tbl_bytes);
    zxlogf(TRACE, "[%s] MSI-X pending table bar %u @ %#x-%#zx", addr(), pba_bar_, pba_offset_,
           pba_offset_ + pba_bytes);
    // Treat each bar as separate to simplify the configuration logic. Size checks
    // double as a way to ensure the bars are valid.
    if (tbar.size < table_offset_ + tbl_bytes) {
      zxlogf(ERROR, "[%s] MSI-X table doesn't fit within BAR %u size of %#zx", addr(), table_bar_,
             tbar.size);
      return ZX_ERR_BAD_STATE;
    }

    if (pbar.size < pba_offset_ + pba_bytes) {
      zxlogf(ERROR, "[%s] MSI-X pba doesn't fit within BAR %u size of %#zx", addr(), pba_bar_,
             pbar.size);
      return ZX_ERR_BAD_STATE;
    }

    zx::vmo table_vmo;
    zx_status_t st = tbar.allocation->CreateVmObject(&table_vmo);
    if (st != ZX_OK) {
      zxlogf(ERROR, "[%s] Couldn't allocate VMO for MSI-X table bar: %d", addr(), st);
      return st;
    }

    zx::vmo pba_vmo;
    st = pbar.allocation->CreateVmObject(&pba_vmo);
    if (st != ZX_OK) {
      zxlogf(ERROR, "[%s] Couldn't allocate VMO for MSI-X pba bar: %d", addr(), st);
      return st;
    }

    st = ddk::MmioBuffer::Create(table_offset_, tbl_bytes, std::move(table_vmo),
                                 ZX_CACHE_POLICY_UNCACHED_DEVICE, &table_mmio_);
    if (st != ZX_OK) {
      zxlogf(ERROR, "[%s] Couldn't map MSI-X table: %d", addr(), st);
      return st;
    }
    table_ = static_cast<MMIO_PTR MsixTable*>(table_mmio_->get());

    st = ddk::MmioBuffer::Create(pba_offset_, pba_bytes, std::move(pba_vmo),
                                 ZX_CACHE_POLICY_UNCACHED_DEVICE, &pba_mmio_);
    if (st != ZX_OK) {
      zxlogf(ERROR, "[%s] Couldn't map MSI-X pba: %d", addr(), st);
      return st;
    }
    pba_ = static_cast<MMIO_PTR uint64_t*>(pba_mmio_->get());
    return ZX_OK;
  }

  const PciReg16 ctrl() { return ctrl_; }
  const PciReg32 table() { return table_reg_; }
  const PciReg32 pba() { return pba_reg_; }
  uint8_t table_bar() { return table_bar_; }
  uint32_t table_offset() { return table_offset_; }
  zx::unowned_vmo table_vmo() { return table_mmio_->get_vmo(); }
  uint16_t table_size() { return std::min(kMaxMsixVectors, table_size_); }
  uint8_t pba_bar() { return pba_bar_; }
  uint32_t pba_offset() { return pba_offset_; }

 private:
  // MSI-X supports up to 2048 vectors, but our system only processes vectors on
  // the bootstrap cpu. There is a real risk that a given device function can
  // exhaust our IRQ pool, though it's unlikely outside of server class
  // hardware. For now, limit an individual function to 8 vectors by reporting
  // a limited table size.
  static constexpr uint16_t kMaxMsixVectors = 8u;
  // Mapped tables for the capability. They may share the same page, but it's impossible
  // to know until runtime.
  std::optional<ddk::MmioBuffer> table_mmio_;
  std::optional<ddk::MmioBuffer> pba_mmio_;
  MMIO_PTR MsixTable* table_;
  MMIO_PTR uint64_t* pba_;
  // Registers for capability configuration and control.
  const PciReg16 ctrl_;
  const PciReg32 table_reg_;
  const PciReg32 pba_reg_;
  // Read-only values cached at initialization.
  uint32_t table_offset_;
  uint32_t pba_offset_;
  uint16_t table_size_;
  uint8_t table_bar_;
  uint8_t pba_bar_;
  bool inited_ = false;
};

}  // namespace pci

#endif  // SRC_DEVICES_BUS_DRIVERS_PCI_CAPABILITIES_MSIX_H_
