// Copyright 2016 The Fuchsia Authors
//
// 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

#if WITH_KERNEL_PCIE

#include "object/pci_device_dispatcher.h"

#include <assert.h>
#include <lib/counters.h>
#include <trace.h>
#include <zircon/errors.h>
#include <zircon/rights.h>

#include <fbl/alloc_checker.h>
#include <fbl/auto_lock.h>
#include <kernel/auto_lock.h>
#include <object/pci_interrupt_dispatcher.h>
#include <object/process_dispatcher.h>

KCOUNTER(dispatcher_pci_device_create_count, "dispatcher.pci_device.create")
KCOUNTER(dispatcher_pci_device_destroy_count, "dispatcher.pci_device.destroy")

zx_status_t PciDeviceDispatcher::Create(uint32_t index, zx_pcie_device_info_t* out_info,
                                        KernelHandle<PciDeviceDispatcher>* out_handle,
                                        zx_rights_t* out_rights) {
  auto bus_drv = PcieBusDriver::GetDriver();
  if (bus_drv == nullptr)
    return ZX_ERR_BAD_STATE;

  auto device = bus_drv->GetNthDevice(index);
  if (device == nullptr)
    return ZX_ERR_OUT_OF_RANGE;

  fbl::AllocChecker ac;
  KernelHandle new_handle(
      fbl::AdoptRef(new (&ac) PciDeviceDispatcher(ktl::move(device), out_info)));
  if (!ac.check())
    return ZX_ERR_NO_MEMORY;

  *out_handle = ktl::move(new_handle);
  *out_rights = default_rights();
  return ZX_OK;
}

PciDeviceDispatcher::PciDeviceDispatcher(fbl::RefPtr<PcieDevice> device,
                                         zx_pcie_device_info_t* out_info)
    : device_(device) {
  kcounter_add(dispatcher_pci_device_create_count, 1);

  out_info->vendor_id = device_->vendor_id();
  out_info->device_id = device_->device_id();
  out_info->base_class = device_->class_id();
  out_info->sub_class = device_->subclass();
  out_info->program_interface = device_->prog_if();
  out_info->revision_id = device_->rev_id();
  out_info->bus_id = static_cast<uint8_t>(device_->bus_id());
  out_info->dev_id = static_cast<uint8_t>(device_->dev_id());
  out_info->func_id = static_cast<uint8_t>(device_->func_id());
}

PciDeviceDispatcher::~PciDeviceDispatcher() {
  // Bus mastering and IRQ configuration are two states that should be
  // disabled when the driver using them has been unloaded.
  DEBUG_ASSERT(device_);

  kcounter_add(dispatcher_pci_device_destroy_count, 1);

  zx_status_t s = EnableBusMaster(false);
  if (s != ZX_OK) {
    printf("Failed to disable bus mastering on %02x:%02x:%1x\n", device_->bus_id(),
           device_->dev_id(), device_->func_id());
  }

  s = SetIrqMode(static_cast<zx_pci_irq_mode_t>(PCIE_IRQ_MODE_DISABLED), 0);
  if (s != ZX_OK) {
    printf("Failed to disable IRQs on %02x:%02x:%1x\n", device_->bus_id(), device_->dev_id(),
           device_->func_id());
  }

  // Release our reference to the underlying PCI device state to indicate that
  // we are now closed.
  //
  // Note: we should not need the lock at this point in time.  We are
  // destructing, if there are any other threads interacting with methods in
  // this object, then we have a serious lifecycle management problem.

  device_ = nullptr;
}

zx_status_t PciDeviceDispatcher::EnableBusMaster(bool enable) {
  canary_.Assert();

  Guard<Mutex> guard{&lock_};
  DEBUG_ASSERT(device_);

  device_->EnableBusMaster(enable);

  return ZX_OK;
}

zx_status_t PciDeviceDispatcher::EnablePio(bool enable) {
  canary_.Assert();

  Guard<Mutex> guard{&lock_};
  DEBUG_ASSERT(device_);

  device_->EnablePio(enable);

  return ZX_OK;
}

zx_status_t PciDeviceDispatcher::EnableMmio(bool enable) {
  canary_.Assert();

  Guard<Mutex> guard{&lock_};
  DEBUG_ASSERT(device_ && device_);

  device_->EnableMmio(enable);

  return ZX_OK;
}

const pcie_bar_info_t* PciDeviceDispatcher::GetBar(uint32_t bar_num) {
  Guard<Mutex> guard{&lock_};
  DEBUG_ASSERT(device_);

  return device_->GetBarInfo(bar_num);
}

zx_status_t PciDeviceDispatcher::GetConfig(pci_config_info_t* out) {
  Guard<Mutex> guard{&lock_};
  DEBUG_ASSERT(device_);

  if (!out) {
    return ZX_ERR_INVALID_ARGS;
  }

  auto cfg = device_->config();
  out->size = (device_->is_pcie()) ? PCIE_EXTENDED_CONFIG_SIZE : PCIE_BASE_CONFIG_SIZE;
  out->base_addr = cfg->base();
  out->is_mmio = (cfg->addr_space() == PciAddrSpace::MMIO);

  return ZX_OK;
}

zx_status_t PciDeviceDispatcher::ResetDevice() {
  canary_.Assert();

  Guard<Mutex> guard{&lock_};
  DEBUG_ASSERT(device_);

  return device_->DoFunctionLevelReset();
}

zx_status_t PciDeviceDispatcher::MapInterrupt(int32_t which_irq,
                                              KernelHandle<InterruptDispatcher>* interrupt_handle,
                                              zx_rights_t* rights) {
  canary_.Assert();

  Guard<Mutex> guard{&lock_};
  DEBUG_ASSERT(device_);

  if ((which_irq < 0) || (static_cast<uint32_t>(which_irq) >= irqs_avail_cnt_))
    return ZX_ERR_INVALID_ARGS;

  // Attempt to create the dispatcher.  It will take care of things like checking for
  // duplicate registration.
  return PciInterruptDispatcher::Create(device_, which_irq, irqs_maskable_, rights,
                                        interrupt_handle);
}

static_assert(static_cast<uint>(ZX_PCIE_IRQ_MODE_DISABLED) ==
                  static_cast<uint>(PCIE_IRQ_MODE_DISABLED),
              "Mode mismatch, ZX_PCIE_IRQ_MODE_DISABLED != PCIE_IRQ_MODE_DISABLED");
static_assert(static_cast<uint>(ZX_PCIE_IRQ_MODE_LEGACY) == static_cast<uint>(PCIE_IRQ_MODE_LEGACY),
              "Mode mismatch, ZX_PCIE_IRQ_MODE_LEGACY != PCIE_IRQ_MODE_LEGACY");
static_assert(static_cast<uint>(ZX_PCIE_IRQ_MODE_MSI) == static_cast<uint>(PCIE_IRQ_MODE_MSI),
              "Mode mismatch, ZX_PCIE_IRQ_MODE_MSI != PCIE_IRQ_MODE_MSI");
static_assert(static_cast<uint>(ZX_PCIE_IRQ_MODE_MSI_X) == static_cast<uint>(PCIE_IRQ_MODE_MSI_X),
              "Mode mismatch, ZX_PCIE_IRQ_MODE_MSI_X != PCIE_IRQ_MODE_MSI_X");
zx_status_t PciDeviceDispatcher::QueryIrqModeCaps(zx_pci_irq_mode_t mode, uint32_t* out_max_irqs) {
  Guard<Mutex> guard{&lock_};
  DEBUG_ASSERT(device_);

  pcie_irq_mode_caps_t caps;
  zx_status_t ret = device_->QueryIrqModeCapabilities(static_cast<pcie_irq_mode_t>(mode), &caps);

  *out_max_irqs = (ret == ZX_OK) ? caps.max_irqs : 0;
  return ret;
}

zx_status_t PciDeviceDispatcher::SetIrqMode(zx_pci_irq_mode_t mode, uint32_t requested_irq_count) {
  canary_.Assert();

  Guard<Mutex> guard{&lock_};
  DEBUG_ASSERT(device_);

  if (mode == ZX_PCIE_IRQ_MODE_DISABLED)
    requested_irq_count = 0;

  zx_status_t ret;
  ret = device_->SetIrqMode(static_cast<pcie_irq_mode_t>(mode), requested_irq_count);
  if (ret == ZX_OK) {
    pcie_irq_mode_caps_t caps;
    ret = device_->QueryIrqModeCapabilities(static_cast<pcie_irq_mode_t>(mode), &caps);

    // The only way for QueryIrqMode to fail at this point should be for the
    // device to have become unplugged.
    if (ret == ZX_OK) {
      irqs_avail_cnt_ = requested_irq_count;
      irqs_maskable_ = caps.per_vector_masking_supported;
    } else {
      device_->SetIrqMode(PCIE_IRQ_MODE_DISABLED, 0);
      irqs_avail_cnt_ = 0;
      irqs_maskable_ = false;
    }
  }

  return ret;
}

#endif  // if WITH_KERNEL_PCIE
