// Copyright 2016 The Fuchsia Authors
// Copyright (c) 2009 Corey Tabaka
// Copyright (c) 2015 Intel Corporation
// Copyright (c) 2016 Travis Geiselbrecht
//
// 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 <inttypes.h>
#include <string.h>
#include <trace.h>
#include <zircon/syscalls/pci.h>
#include <zircon/types.h>

#include <dev/interrupt.h>
#include <dev/pcie_bus_driver.h>
#include <dev/pcie_platform.h>
#include <kernel/mutex.h>
#include <ktl/limits.h>
#include <lk/init.h>
#include <platform/pc/bootloader.h>

class X86PciePlatformSupport : public PciePlatformInterface {
 public:
  X86PciePlatformSupport() : PciePlatformInterface(MsiSupportLevel::MSI) {}
  zx_status_t AllocMsiBlock(uint requested_irqs, bool can_target_64bit, bool is_msix,
                            msi_block_t* out_block) override {
    return msi_alloc_block(requested_irqs, can_target_64bit, is_msix, out_block);
  }

  void FreeMsiBlock(msi_block_t* block) override { msi_free_block(block); }

  void RegisterMsiHandler(const msi_block_t* block, uint msi_id, int_handler handler,
                          void* ctx) override {
    msi_register_handler(block, msi_id, handler, ctx);
  }
};

X86PciePlatformSupport platform_pcie_support;

static void lockdown_pcie_bus_regions(PcieBusDriver& pcie) {
  // If we get to this point, something has gone Extremely Wrong.  Attempt to
  // remove all possible allocatable bus addresses from the PCIe bus driver.
  // This should *never* fail.  If it does, halt and catch fire, even in a
  // release build.
  zx_status_t res;
  res = pcie.SubtractBusRegion(0x0, 0x10000, PciAddrSpace::PIO);
  ASSERT(res == ZX_OK);

  res = pcie.SubtractBusRegion(0x0, ktl::numeric_limits<uint64_t>::max(), PciAddrSpace::MMIO);
  ASSERT(res == ZX_OK);
}

static void x86_pcie_init_hook(uint level) {
  // Initialize the bus driver
  zx_status_t res = PcieBusDriver::InitializeDriver(platform_pcie_support);
  if (res != ZX_OK) {
    TRACEF(
        "Failed to initialize PCI bus driver (res = %d).  "
        "PCI will be non-functional.\n",
        res);
    return;
  }

  auto pcie = PcieBusDriver::GetDriver();
  DEBUG_ASSERT(pcie != nullptr);

  // Compute the initial set of PIO/MMIO bus regions which PCIe is allowed to
  // allocate to devices for BAR windows.
  //
  // TODO(johngro) : do a better job of computing the valid initial PIO
  // regions we are permitted to use.  Right now, we just hardcode it.
  constexpr uint64_t pcie_pio_base = 0x8000;
  constexpr uint64_t pcie_pio_size = 0x10000 - pcie_pio_base;

  res = pcie->AddBusRegion(pcie_pio_base, pcie_pio_size, PciAddrSpace::PIO);
  if (res != ZX_OK) {
    TRACEF(
        "WARNING - Failed to add initial PCIe PIO region "
        "[%" PRIx64 ", %" PRIx64 ") to bus driver! (res %d)\n",
        pcie_pio_base, pcie_pio_base + pcie_pio_size, res);
  }

  // TODO(johngro) : Right now, we add only the low memory (< 4GB) region to
  // the allocatable set and then subtract out everything else.  Someday, we
  // should really add in the entire 64-bit address space as a starting point.
  //
  // Also, we may want to consider unconditionally subtracting out the region
  // from [0xFEC00000, 4 << 30).  x86/64 architecture specific registers tend
  // to live here and it would be Very Bad to allow PCI to allocate BARs in
  // this region.  In theory, this region should be listed in the e820 map
  // given to us by the bootloader/BIOS, but bootloaders have been known to
  // make mistakes in the past.
  constexpr uint64_t pcie_mmio_base = 0x0;
  constexpr uint64_t pcie_mmio_size = 0x100000000;
  res = pcie->AddBusRegion(pcie_mmio_base, pcie_mmio_size, PciAddrSpace::MMIO);
  if (res != ZX_OK) {
    TRACEF(
        "WARNING - Failed to add initial PCIe MMIO region "
        "[%" PRIx64 ", %" PRIx64 ") to bus driver! (res %d)\n",
        pcie_mmio_base, pcie_mmio_base + pcie_mmio_size, res);
    return;
  }

  for (const zbi_mem_range_t& range : bootloader.memory_ranges) {
    zx_status_t result = pcie->SubtractBusRegion(range.paddr, range.length, PciAddrSpace::MMIO);
    if (result != ZX_OK) {
      // Woah, this is Very Bad!  If we failed to prohibit the PCIe bus
      // driver from using a region of the MMIO bus we are in a pretty
      // dangerous situation.  For now, log a message, then attempt to
      // lockdown the bus.
      TRACEF(
          "FATAL ERROR - Failed to subtract PCIe MMIO region "
          "[%" PRIx64 ", %" PRIx64 ") from bus driver! (res %d)\n",
          range.paddr, range.paddr + range.length, result);
      lockdown_pcie_bus_regions(*pcie);
      return;
    }
  }
}

LK_INIT_HOOK(x86_pcie_init, x86_pcie_init_hook, LK_INIT_LEVEL_PLATFORM)

#endif  // WITH_KERNEL_PCIE
