// Copyright 2016 The Fuchsia Authors
// Copyright (c) 2016, Google, Inc. All rights reserved
//
// 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

#include <assert.h>
#include <debug.h>
#include <inttypes.h>
#include <platform.h>
#include <string.h>
#include <trace.h>
#include <zircon/compiler.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <dev/interrupt.h>
#include <dev/pcie_bridge.h>
#include <dev/pcie_root.h>
#include <fbl/algorithm.h>
#include <kernel/mutex.h>
#include <kernel/spinlock.h>
#include <ktl/iterator.h>
#include <vm/vm.h>

#define LOCAL_TRACE 0

PcieUpstreamNode::~PcieUpstreamNode() {
  if constexpr (DEBUG_ASSERT_IMPLEMENTED) {
    // Sanity check to make sure that all child devices have been released as
    // well.
    for (size_t i = 0; i < ktl::size(downstream_); ++i)
      DEBUG_ASSERT(!downstream_[i]);
  }
}

void PcieUpstreamNode::AllocateDownstreamBars() {
  /* Finally, allocate all of the BARs for our downstream devices.  Make sure
   * to not access our downstream devices directly.  Instead, hold references
   * to downstream devices we obtain while holding bus driver's topology lock.
   * */
  for (uint i = 0; i < ktl::size(downstream_); ++i) {
    auto device = GetDownstream(i);
    if (device != nullptr) {
      zx_status_t res = device->AllocateBars();
      if (res != ZX_OK)
        device->Disable();
    }
  }
}

void PcieUpstreamNode::DisableDownstream() {
  for (uint i = 0; i < ktl::size(downstream_); ++i) {
    auto downstream_device = GetDownstream(i);
    if (downstream_device)
      downstream_device->Disable();
  }
}

void PcieUpstreamNode::UnplugDownstream() {
  for (uint i = 0; i < ktl::size(downstream_); ++i) {
    auto downstream_device = GetDownstream(i);
    if (downstream_device)
      downstream_device->Unplug();
  }
}

void PcieUpstreamNode::ScanDownstream() {
  DEBUG_ASSERT(driver().RescanLockIsHeld());

  for (uint dev_id = 0; dev_id < PCIE_MAX_DEVICES_PER_BUS; ++dev_id) {
    for (uint func_id = 0; func_id < PCIE_MAX_FUNCTIONS_PER_DEVICE; ++func_id) {
      /* If we can find the config, and it has a valid vendor ID, go ahead
       * and scan it looking for a valid function. */
      auto cfg = driver().GetConfig(managed_bus_id_, dev_id, func_id);
      if (cfg == nullptr) {
        TRACEF("Warning: bus being scanned is outside ecam region!\n");
        return;
      }

      uint16_t vendor_id = cfg->Read(PciConfig::kVendorId);
      bool good_device = cfg && (vendor_id != PCIE_INVALID_VENDOR_ID);
      if (good_device) {
        uint16_t device_id = cfg->Read(PciConfig::kDeviceId);
        LTRACEF("found valid device %04x:%04x at %02x:%02x.%01x\n", vendor_id, device_id,
                managed_bus_id_, dev_id, func_id);
        /* Don't scan the function again if we have already discovered
         * it.  If this function happens to be a bridge, go ahead and
         * look under it for new devices. */
        uint ndx = (dev_id * PCIE_MAX_FUNCTIONS_PER_DEVICE) + func_id;
        DEBUG_ASSERT(ndx < ktl::size(downstream_));

        auto downstream_device = GetDownstream(ndx);
        if (!downstream_device) {
          auto new_dev = ScanDevice(cfg, dev_id, func_id);
          if (new_dev == nullptr) {
            TRACEF(
                "Failed to initialize device %02x:%02x.%01x; This is Very Bad.  "
                "Device (and any of its children) will be inaccessible!\n",
                managed_bus_id_, dev_id, func_id);
            good_device = false;
          }
        } else if (downstream_device->is_bridge()) {
          // TODO(johngro) : Instead of going up and down the class graph with static
          // casts, would it be better to do this with vtable tricks?
          static_cast<PcieUpstreamNode*>(static_cast<PcieBridge*>(downstream_device.get()))
              ->ScanDownstream();
        }
      }

      /* If this was function zero, and there is either no device, or the
       * config's header type indicates that this is not a multi-function
       * device, then just move on to the next device. */
      if (!func_id &&
          (!good_device || !(cfg->Read(PciConfig::kHeaderType) & PCI_HEADER_TYPE_MULTI_FN)))
        break;
    }
  }
}

fbl::RefPtr<PcieDevice> PcieUpstreamNode::ScanDevice(const PciConfig* cfg, uint dev_id,
                                                     uint func_id) {
  DEBUG_ASSERT(cfg);
  DEBUG_ASSERT(dev_id < PCIE_MAX_DEVICES_PER_BUS);
  DEBUG_ASSERT(func_id < PCIE_MAX_FUNCTIONS_PER_DEVICE);
  DEBUG_ASSERT(driver().RescanLockIsHeld());

  __UNUSED uint ndx = (dev_id * PCIE_MAX_FUNCTIONS_PER_DEVICE) + func_id;
  DEBUG_ASSERT(ndx < ktl::size(downstream_));
  DEBUG_ASSERT(downstream_[ndx] == nullptr);

  LTRACEF("Scanning new function at %02x:%02x.%01x\n", managed_bus_id_, dev_id, func_id);

  /* Is there an actual device here? */
  uint16_t vendor_id = cfg->Read(PciConfig::kVendorId);
  if (vendor_id == PCIE_INVALID_VENDOR_ID) {
    LTRACEF("Bad vendor ID (0x%04hx) when looking for PCIe device at %02x:%02x.%01x\n", vendor_id,
            managed_bus_id_, dev_id, func_id);
    return nullptr;
  }

  // Create the either a PcieBridge or a PcieDevice based on the configuration
  // header type.
  uint8_t header_type = cfg->Read(PciConfig::kHeaderType) & PCI_HEADER_TYPE_MASK;
  if (header_type == PCI_HEADER_TYPE_PCI_BRIDGE) {
    uint secondary_id = cfg->Read(PciConfig::kSecondaryBusId);
    return PcieBridge::Create(*this, dev_id, func_id, secondary_id);
  }

  return PcieDevice::Create(*this, dev_id, func_id);
}
