// Copyright 2016 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 "allocation.h"
#include "bridge.h"
#include "bus.h"
#include "common.h"
#include "config.h"
#include "device.h"
#include <assert.h>
#include <err.h>
#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <inttypes.h>
#include <limits.h>
#include <string.h>
#include <zircon/compiler.h>

namespace pci {

// Bridges rely on most of the protected Device members when they can
Bridge::Bridge(zx_device_t* parent, std::unique_ptr<Config>&& config, UpstreamNode* upstream,
               BusLinkInterface* bli, uint8_t mbus_id)
    : pci::Device(parent, std::move(config), upstream, bli, true),
      UpstreamNode(UpstreamNode::Type::BRIDGE, mbus_id) {}

zx_status_t Bridge::Create(zx_device_t* parent, std::unique_ptr<Config>&& config,
                           UpstreamNode* upstream, BusLinkInterface* bli, uint8_t managed_bus_id,
                           fbl::RefPtr<pci::Bridge>* out_bridge) {
  fbl::AllocChecker ac;
  auto raw_bridge = new (&ac) Bridge(parent, std::move(config), upstream, bli, managed_bus_id);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  zx_status_t status = raw_bridge->Init();
  if (status != ZX_OK) {
    delete raw_bridge;
    return status;
  }

  fbl::RefPtr<pci::Device> dev = fbl::AdoptRef(raw_bridge);
  bli->LinkDevice(dev);
  *out_bridge = fbl::RefPtr<Bridge>::Downcast(dev);
  return ZX_OK;
}

zx_status_t Bridge::Init() {
  fbl::AutoLock dev_lock(&dev_lock_);

  // Initialize the device portion of ourselves first. This will handle initializing
  // bars/capabilities, and linking ourselves upstream before we need the information
  // for our own window allocation.
  zx_status_t status = pci::Device::InitLocked();
  if (status != ZX_OK) {
    return status;
  }

  // Sanity checks of bus allocation.
  //
  // TODO(cja) : Strengthen sanity checks around bridge topology and
  // handle the need to reconfigure bridge topology if a bridge happens to be
  // misconfigured.  Right now, we just assume that the BIOS/Bootloader has
  // taken care of bridge configuration.  In the short term, it would be good
  // to add some protection against cycles in the bridge configuration which
  // could lead to infinite recursion.
  uint8_t primary_id = cfg_->Read(Config::kPrimaryBusId);
  uint8_t secondary_id = cfg_->Read(Config::kSecondaryBusId);

  if (primary_id == secondary_id) {
    pci_errorf(
        "PCI-to-PCI bridge detected at %s claims to be bridged to itsef "
        "(primary %02x == secondary %02x)... skipping scan.\n",
        cfg_->addr(), primary_id, secondary_id);
    return ZX_ERR_BAD_STATE;
  }

  if (primary_id != cfg_->bdf().bus_id) {
    pci_errorf(
        "PCI-to-PCI bridge detected at %s has invalid primary bus id "
        "(%02x)... skipping scan.\n",
        cfg_->addr(), primary_id);
    return ZX_ERR_BAD_STATE;
  }

  if (secondary_id != managed_bus_id()) {
    pci_errorf(
        "PCI-to-PCI bridge detected at %s has invalid secondary bus id "
        "(%02x)... skipping scan.\n",
        cfg_->addr(), secondary_id);
    return ZX_ERR_BAD_STATE;
  }

  // Parse the state of its I/O and Memory windows.
  status = ParseBusWindowsLocked();
  if (status != ZX_OK) {
    return status;
  }

  // Allocate enough space in a region pool to account for the worst case
  // scenario of having the max number of functions under a bridge. Bridge
  // window allocations aren't a problem because the max bars per device is 6,
  // which is larger than the 5 allocations a bridge might need for 2 bars and
  // 3 window allocations. Presently, this comes out to a a max of ~132 KB of
  // space if we were to meet that upper bound. RegionPools are slab
  // allocators that scale up as needed, so the initial allocation is roughly
  // a page, and will grow as necessary so we won't pay this cost unless we
  // need to.
  constexpr uint32_t pool_size =
      sizeof(RegionAllocator::Region) * (PCI_MAX_FUNCTIONS_PER_BUS * PCI_MAX_BAR_REGS);
  constexpr uint32_t pool_size_aligned = fbl::round_up(pool_size, PAGE_SIZE * 1u);
  auto allocator_pool_ = RegionAllocator::RegionPool::Create(pool_size_aligned);
  if (allocator_pool_ == nullptr) {
    return ZX_ERR_NO_MEMORY;
  }

  mmio_regions_.SetRegionPool(allocator_pool_);
  pf_mmio_regions_.SetRegionPool(allocator_pool_);
  pio_regions_.SetRegionPool(allocator_pool_);

  // Things went well and the device is in a good state. Add ourself to the upstream
  // graph and mark as plugged in.
  upstream_->LinkDevice(static_cast<pci::Device*>(this));
  plugged_in_ = true;
  return ZX_OK;
}

zx_status_t Bridge::ParseBusWindowsLocked() {
  // Parse the currently configured windows used to determine MMIO/PIO
  // forwarding policy for this bridge.
  //
  // See The PCI-to-PCI Bridge Architecture Specification Revision 1.2,
  // section 3.2.5 and chapter 4 for detail.
  uint32_t base, limit;

  // I/O window
  base = cfg_->Read(Config::kIoBase);
  limit = cfg_->Read(Config::kIoLimit);

  supports_32bit_pio_ = ((base & 0xF) == 0x1) && ((base & 0xF) == (limit & 0xF));
  io_base_ = (base & ~0xF) << 8;
  io_limit_ = (limit << 8) | 0xFFF;
  if (supports_32bit_pio_) {
    io_base_ |= static_cast<uint32_t>(cfg_->Read(Config::kIoBaseUpper)) << 16;
    io_limit_ |= static_cast<uint32_t>(cfg_->Read(Config::kIoLimitUpper)) << 16;
  }

  // Non-prefetchable memory window
  mem_base_ = (static_cast<uint32_t>(cfg_->Read(Config::kMemoryBase)) << 16) & ~0xFFFFF;
  mem_limit_ = (static_cast<uint32_t>(cfg_->Read(Config::kMemoryLimit)) << 16) | 0xFFFFF;

  // Prefetchable memory window
  base = cfg_->Read(Config::kPrefetchableMemoryBase);
  limit = cfg_->Read(Config::kPrefetchableMemoryLimit);

  bool supports_64bit_pf_mem = ((base & 0xF) == 0x1) && ((base & 0xF) == (limit & 0xF));
  pf_mem_base_ = (base & ~0xF) << 16;
  pf_mem_limit_ = (limit << 16) | 0xFFFFF;
  if (supports_64bit_pf_mem) {
    pf_mem_base_ |= static_cast<uint64_t>(cfg_->Read(Config::kPrefetchableMemoryBaseUpper)) << 32;
    pf_mem_limit_ |= static_cast<uint64_t>(cfg_->Read(Config::kPrefetchableMemoryLimitUpper)) << 32;
  }

  return ZX_OK;
}

void Bridge::Dump() const {
  pci::Device::Dump();

  pci_infof("  managed bus id: %#02x\n", managed_bus_id());
  if (io_limit() > io_base()) {
    pci_infof("       io window: [%#04x-%#04x]\n", io_base(), io_limit());
  }
  if (mem_limit() > mem_base()) {
    pci_infof("     mmio window: [%#08x-%#08x]\n", mem_base(), mem_limit());
  }
  if (pf_mem_limit() > pf_mem_base()) {
    pci_infof("  pf-mmio window: [%#" PRIx64 "-%#" PRIx64 "]\n", pf_mem_base(), pf_mem_limit());
  }
}

void Bridge::Unplug() {
  UnplugDownstream();
  pci::Device::Unplug();
  pci_infof("bridge [%s] unplugged\n", cfg_->addr());
}

zx_status_t Bridge::ConfigureBars() {
  zx_status_t status = ZX_OK;
  {
    fbl::AutoLock dev_lock(&dev_lock_);
    status = AllocateBridgeWindowsLocked();
    if (status != ZX_OK) {
      return status;
    }
  }

  status = pci::Device::ConfigureBars();
  if (status != ZX_OK) {
    return status;
  }

  ConfigureDownstreamBars();
  return ZX_OK;
}

zx_status_t Bridge::AllocateBridgeWindowsLocked() {
  ZX_DEBUG_ASSERT(upstream_);

  // We are configuring a bridge.  We need to be able to allocate the MMIO and
  // PIO regions this bridge is configured to manage.
  //
  // Bridges support IO, MMIO, and PF-MMIO routing. Non-prefetchable MMIO is
  // limited to 32 bit addresses, whereas PF-MMIO can be in a 64 bit window.
  // Each bridge receives a set of PciAllocation objects from their upstream
  // that covers their address space windows for transactions, and then add
  // those ranges to their own allocators. Those are then used to allocate for
  // bridges and device endpoints further downstream.
  //
  // TODO(cja) : support dynamic configuration of bridge windows.  Its going
  // to be important when we need to support hot-plugging.  See ZX-321

  zx_status_t status;
  fbl::unique_ptr<PciAllocation> alloc;

  // Every window is configured the same butwith different allocators and registers.
  auto configure_window = [&](auto& upstream_alloc, auto& dest_alloc, auto base, auto limit,
                              auto label) {
    if (base <= limit) {
      uint64_t size = static_cast<uint64_t>(limit) - base + 1;
      status = upstream_alloc.AllocateWindow(base, size, &alloc);

      if (status != ZX_OK) {
        pci_errorf("[%s] Failed to allocate bridge %s window [%016lx-%016lx]\n", cfg_->addr(),
                   label, static_cast<uint64_t>(base), static_cast<uint64_t>(limit));
        return status;
      }

      ZX_DEBUG_ASSERT(alloc != nullptr);
      return dest_alloc.GrantAddressSpace(std::move(alloc));
    }
    return ZX_OK;
  };

  // Configure the three windows
  status = configure_window(upstream_->pio_regions(), pio_regions_, io_base_, io_limit_, "io");
  if (status != ZX_OK) {
    pci_tracef("%s bailing out after pio\n", cfg_->addr());
    return status;
  }
  status =
      configure_window(upstream_->mmio_regions(), mmio_regions_, mem_base_, mem_limit_, "mmio");
  if (status != ZX_OK) {
    pci_tracef("%s bailing out after mmio\n", cfg_->addr());
    return status;
  }
  status = configure_window(upstream_->pf_mmio_regions(), pf_mmio_regions_, pf_mem_base_,
                            pf_mem_limit_, "pf_mmio");
  if (status != ZX_OK) {
    pci_tracef("%s bailing out after pf-mmio\n", cfg_->addr());
    return status;
  }

  return ZX_OK;
}

void Bridge::Disable() {
  // Immediately enter the device lock and enter the disabled state.  We want
  // to be outside of the device lock as we disable our downstream devices,
  // but we don't want any new devices to be able to plug into us as we do so.
  {
    fbl::AutoLock dev_lock(&dev_lock_);
    disabled_ = true;
  }

  // Start by disabling all of our downstream devices.  This should prevent
  // them from bothering us moving forward.  Do not hold the device lock while
  // we do this.
  DisableDownstream();

  // Enter the device lock again and finish shooting ourselves in the head.
  {
    fbl::AutoLock dev_lock(&dev_lock_);

    // Disable the device portion of ourselves.
    Device::DisableLocked();

    // Close all of our IO windows at the HW level and update the internal
    // bookkeeping to indicate that they are closed.
    cfg_->Write(Config::kIoBase, 0xF0);
    cfg_->Write(Config::kIoLimit, 0);
    cfg_->Write(Config::kIoBaseUpper, 0);
    cfg_->Write(Config::kIoLimitUpper, 0);

    cfg_->Write(Config::kMemoryBase, 0xFFF0);
    cfg_->Write(Config::kMemoryLimit, 0);

    cfg_->Write(Config::kPrefetchableMemoryBase, 0xFFF0);
    cfg_->Write(Config::kPrefetchableMemoryLimit, 0);
    cfg_->Write(Config::kPrefetchableMemoryBaseUpper, 0);
    cfg_->Write(Config::kPrefetchableMemoryLimitUpper, 0);

    pf_mem_limit_ = mem_limit_ = io_limit_ = 0u;
    pf_mem_base_ = mem_base_ = io_base_ = 1u;
  }
}

}  // namespace pci
