// 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 "usb-xhci.h"

#include <lib/device-protocol/pci.h>
#include <lib/zx/bti.h>
#include <lib/zx/interrupt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <algorithm>
#include <memory>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/platform-defs.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_call.h>
#include <hw/arch_ops.h>
#include <hw/reg.h>

#include "xdc.h"
#include "xhci-device-manager.h"
#include "xhci-root-hub.h"
#include "xhci-util.h"
#include "xhci.h"

namespace usb_xhci {

#define MAX_SLOTS 255

#define PDEV_MMIO_INDEX 0
#define PDEV_IRQ_INDEX 0

zx_status_t xhci_add_device(xhci_t* xhci, int slot_id, int hub_address, int speed) {
  zxlogf(DEBUG, "xhci_add_new_device");

  if (!xhci->bus.ops) {
    zxlogf(ERROR, "no bus device in xhci_add_device");
    return ZX_ERR_INTERNAL;
  }

  return usb_bus_interface_add_device(&xhci->bus, slot_id, hub_address, speed);
}

void xhci_remove_device(xhci_t* xhci, int slot_id) {
  zxlogf(DEBUG, "xhci_remove_device %d", slot_id);

  if (!xhci->bus.ops) {
    zxlogf(ERROR, "no bus device in xhci_remove_device");
    return;
  }

  usb_bus_interface_remove_device(&xhci->bus, slot_id);
}

void UsbXhci::UsbHciRequestQueue(usb_request_t* usb_request,
                                 const usb_request_complete_t* complete_cb) {
  xhci_request_queue(xhci_.get(), usb_request, complete_cb);
}

void UsbXhci::UsbHciSetBusInterface(const usb_bus_interface_protocol_t* bus_intf) {
  if (bus_intf) {
    memcpy(&xhci_->bus, bus_intf, sizeof(xhci_->bus));
    // wait until bus driver has started before doing this
    xhci_queue_start_root_hubs(xhci_.get());
  } else {
    memset(&xhci_->bus, 0, sizeof(xhci_->bus));
  }
}

size_t UsbXhci::UsbHciGetMaxDeviceCount() { return xhci_->max_slots + XHCI_RH_COUNT + 1; }

zx_status_t UsbXhci::UsbHciEnableEndpoint(uint32_t device_id,
                                          const usb_endpoint_descriptor_t* ep_desc,
                                          const usb_ss_ep_comp_descriptor_t* ss_com_desc,
                                          bool enable) {
  if (enable) {
    return xhci_enable_endpoint(xhci_.get(), device_id, ep_desc, ss_com_desc);
  } else {
    return xhci_disable_endpoint(xhci_.get(), device_id, ep_desc);
  }
}

uint64_t UsbXhci::UsbHciGetCurrentFrame() { return xhci_get_current_frame(xhci_.get()); }

zx_status_t UsbXhci::UsbHciConfigureHub(uint32_t device_id, usb_speed_t speed,
                                        const usb_hub_descriptor_t* desc, bool multi_tt) {
  return xhci_configure_hub(xhci_.get(), device_id, speed, desc);
}

zx_status_t UsbXhci::UsbHciHubDeviceAdded(uint32_t device_id, uint32_t port, usb_speed_t speed) {
  return xhci_enumerate_device(xhci_.get(), device_id, port, speed);
}

zx_status_t UsbXhci::UsbHciHubDeviceRemoved(uint32_t device_id, uint32_t port) {
  xhci_device_disconnected(xhci_.get(), device_id, port);
  return ZX_OK;
}

zx_status_t UsbXhci::UsbHciHubDeviceReset(uint32_t device_id, uint32_t port) {
  return xhci_device_reset(xhci_.get(), device_id, port);
}

zx_status_t UsbXhci::UsbHciResetEndpoint(uint32_t device_id, uint8_t ep_address) {
  return xhci_reset_endpoint(xhci_.get(), device_id, ep_address);
}

zx_status_t UsbXhci::UsbHciResetDevice(uint32_t hub_address, uint32_t device_id) {
  auto* xhci = xhci_.get();
  auto* slot = &xhci->slots[device_id];
  uint32_t port = slot->port;
  if (slot->hub_address == 0) {
    // Convert real port number to virtual root hub number.
    port = xhci->rh_port_map[port - 1] + 1;
  }
  zxlogf(DEBUG, "xhci_reset_device slot_id: %u port: %u hub_address: %u", device_id, port,
         hub_address);

  return usb_bus_interface_reset_port(&xhci->bus, hub_address, port, false);
}

static size_t xhci_get_max_transfer_size(uint8_t ep_address) {
  if (ep_address == 0) {
    // control requests have uint16 length field so we need to support UINT16_MAX
    // we require one setup, status and data event TRB in addition to data transfer TRBs
    // and subtract one more to account for the link TRB
    static_assert(PAGE_SIZE * (TRANSFER_RING_SIZE - 4) >= UINT16_MAX,
                  "TRANSFER_RING_SIZE too small");
    return UINT16_MAX;
  }
  // non-control transfers consist of normal transfer TRBs plus one data event TRB
  // Subtract 2 to reserve a TRB for data event and to account for the link TRB
  return PAGE_SIZE * (TRANSFER_RING_SIZE - 2);
}

size_t UsbXhci::UsbHciGetMaxTransferSize(uint32_t device_id, uint8_t ep_address) {
  return xhci_get_max_transfer_size(ep_address);
}

zx_status_t UsbXhci::UsbHciCancelAll(uint32_t device_id, uint8_t ep_address) {
  return xhci_cancel_transfers(xhci_.get(), device_id, xhci_endpoint_index(ep_address));
}

size_t UsbXhci::UsbHciGetRequestSize() {
  return sizeof(xhci_usb_request_internal_t) + sizeof(usb_request_t);
}

void xhci_request_queue(xhci_t* xhci, usb_request_t* req,
                        const usb_request_complete_t* complete_cb) {
  zx_status_t status;

  xhci_usb_request_internal_t* req_int = USB_REQ_TO_XHCI_INTERNAL(req);
  req_int->complete_cb = *complete_cb;
  if (req->header.length > xhci_get_max_transfer_size(req->header.ep_address)) {
    status = ZX_ERR_INVALID_ARGS;
  } else {
    status = xhci_queue_transfer(xhci, req);
  }

  if (status != ZX_OK && status != ZX_ERR_BUFFER_TOO_SMALL) {
    usb_request_complete(req, status, 0, complete_cb);
  }
}

static void xhci_shutdown(xhci_t* xhci) {
  // stop the controller and our device thread
  xhci_stop(xhci);
  xhci->suspended.store(true);
  // stop our interrupt threads
  for (uint32_t i = 0; i < xhci->num_interrupts; i++) {
    xhci->irq_handles[i].destroy();
    thrd_join(xhci->completer_threads[i], nullptr);
  }
}

void UsbXhci::DdkSuspend(ddk::SuspendTxn txn) {
  // TODO(fxb/42612) do different things based on the requested_state and suspend reason.
  // for now we shutdown the driver in preparation for mexec
  xhci_shutdown(xhci_.get());
  txn.Reply(ZX_OK, 0);
}

void UsbXhci::DdkUnbindNew(ddk::UnbindTxn txn) {
  zxlogf(INFO, "UsbXhci::DdkUnbind");
  xhci_shutdown(xhci_.get());
  txn.Reply();
}

void UsbXhci::DdkRelease() {
  zxlogf(INFO, "UsbXhci::DdkRelease");
  delete this;
}

int UsbXhci::CompleterThread(void* arg) {
  auto* completer = static_cast<Completer*>(arg);
  auto* xhci = completer->xhci;
  auto interrupter = completer->interrupter;
  auto& interrupt = xhci->irq_handles[interrupter];

  // TODO(johngro): See ZX-940.  Get rid of this.  For now we need thread
  // priorities so that realtime transactions use the completer which ends
  // up getting realtime latency guarantees.
  if (completer->high_priority) {
    if (xhci->profile_handle.is_valid()) {
      zx_object_set_profile(zx_thread_self(), xhci->profile_handle.get(), 0);
    } else {
      zxlogf(WARN,
             "No scheduler profile available to apply to the high priority XHCI completer.  "
             "Service will be best effort.\n");
    }
  }

  while (1) {
    zx_status_t wait_res;
    wait_res = interrupt.wait(nullptr);
    if (wait_res != ZX_OK) {
      if (wait_res != ZX_ERR_CANCELED) {
        zxlogf(ERROR, "unexpected zx_interrupt_wait failure (%d)", wait_res);
      }
      break;
    }
    if (xhci->suspended.load()) {
      // TODO(ravoorir): Remove this hack once the interrupt signalling bug
      // is resolved.
      zxlogf(ERROR, "race in zx_interrupt_cancel triggered. Kick off workaround for now");
      break;
    }
    xhci_handle_interrupt(xhci, interrupter);
  }
  zxlogf(DEBUG, "xhci completer %u thread done", interrupter);
  return 0;
}

int UsbXhci::StartThread() {
  zxlogf(DEBUG, "%s start", __func__);

  auto cleanup = fbl::MakeAutoCall([this]() { DdkRemoveDeprecated(); });

  fbl::AllocChecker ac;
  completers_.reset(new (&ac) Completer[xhci_->num_interrupts], xhci_->num_interrupts);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  for (uint32_t i = 0; i < xhci_->num_interrupts; i++) {
    auto* completer = &completers_[i];
    completer->xhci = xhci_.get();
    completer->interrupter = i;
    // We need a high priority thread for isochronous transfers.
    // If there is only one interrupt available, that thread will need
    // to be high priority.
    completer->high_priority = i == ISOCH_INTERRUPTER || xhci_->num_interrupts == 1;
  }

  // xhci_start will block, so do this part here instead of in usb_xhci_bind
  auto status = xhci_start(xhci_.get());
#if defined(__x86_64__)
  if (status == ZX_OK) {
    // TODO(jocelyndang): start xdc in a new process.
    status = xdc_bind(zxdev(), xhci_->bti_handle.get(), xhci_->mmio->get());
    // XDC is not required for functioning XHCI. Not all boards support XDC.
    if (status != ZX_OK) {
      zxlogf(ERROR, "xhci_start: xdc_bind failed %d", status);
    }
    status = ZX_OK;
  }
#endif

  if (status != ZX_OK) {
    return status;
  }

  DdkMakeVisible();
  for (uint32_t i = 0; i < xhci_->num_interrupts; i++) {
    thrd_create_with_name(&xhci_->completer_threads[i], CompleterThread, &completers_[i],
                          "xhci_completer_thread");
  }

  zxlogf(DEBUG, "%s done", __func__);
  cleanup.cancel();
  return 0;
}

zx_status_t UsbXhci::FinishBind() {
  auto status = DdkAdd("xhci", DEVICE_ADD_INVISIBLE);
  if (status != ZX_OK) {
    return status;
  }

  // Configure and fetch a deadline profile for the high priority USB completer
  // thread.  In a case where we are taking an interrupt on every microframe, we
  // will need to run at 8KHz and have reserved up to 66% of a CPU for work in
  // that period.
  status = device_get_deadline_profile(
      zxdev_,
      ZX_USEC(80),   // capacity: we agree to run for no more than 80 uSec max
      ZX_USEC(120),  // deadline: we need to be done before the next microframe (125 uSec)
      ZX_USEC(120),  // period:   Worst case period is one IRQ per microframe (8KHz)
      "src/devices/usb/drivers/xhci/usb-xhci", xhci_->profile_handle.reset_and_get_address());

  if (status != ZX_OK) {
    zxlogf(WARN, "Failed to obtain scheduler profile for high priority completer (res %d)",
           status);
  }

  thrd_t thread;
  thrd_create_with_name(
      &thread, [](void* arg) -> int { return reinterpret_cast<UsbXhci*>(arg)->StartThread(); },
      reinterpret_cast<void*>(this), "xhci_start_thread");
  thrd_detach(thread);

  return ZX_OK;
}

zx_status_t UsbXhci::InitPci() {
  zx_status_t status;

  fbl::AllocChecker ac;
  xhci_ = std::unique_ptr<xhci_t>(new (&ac) xhci_t);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  status = pci_.GetBti(0, &xhci_->bti_handle);
  if (status != ZX_OK) {
    return status;
  }

  // eXtensible Host Controller Interface revision 1.1, section 5, xhci
  // should only use BARs 0 and 1. 0 for 32 bit addressing, and 0+1 for 64 bit addressing.

  // TODO(voydanoff) find a C++ way to do this
  pci_protocol_t pci;
  pci_.GetProto(&pci);
  mmio_buffer_t mmio;
  status = pci_map_bar_buffer(&pci, 0u, ZX_CACHE_POLICY_UNCACHED, &mmio);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s could not map bar", __func__);
    return status;
  }
  xhci_->mmio = ddk::MmioBuffer(mmio);

  uint32_t irq_cnt;
  irq_cnt = 0;
  status = pci_.QueryIrqMode(ZX_PCIE_IRQ_MODE_MSI, &irq_cnt);
  if (status != ZX_OK) {
    zxlogf(ERROR, "pci_query_irq_mode failed %d", status);
    return status;
  }

  // Cap IRQ count at the number of interrupters we want to use and
  // the number of interrupters supported by XHCI.
  irq_cnt = std::min(irq_cnt, INTERRUPTER_COUNT);
  irq_cnt = std::min(irq_cnt, xhci_get_max_interrupters(xhci_.get()));

  // select our IRQ mode
  xhci_mode_t mode;
  mode = XHCI_PCI_MSI;
  status = pci_.SetIrqMode(ZX_PCIE_IRQ_MODE_MSI, irq_cnt);
  if (status < 0) {
    zxlogf(ERROR, "MSI interrupts not available, irq_cnt: %d, err: %d", irq_cnt, status);
    zx_status_t status_legacy = pci_.SetIrqMode(ZX_PCIE_IRQ_MODE_LEGACY, 1);

    if (status_legacy < 0) {
      zxlogf(ERROR,
             "usb_xhci_bind Failed to set IRQ mode to either MSI "
             "(err = %d) or Legacy (err = %d)\n",
             status, status_legacy);
      return status;
    }

    mode = XHCI_PCI_LEGACY;
    irq_cnt = 1;
  }

  for (uint32_t i = 0; i < irq_cnt; i++) {
    // register for interrupts
    status = pci_.MapInterrupt(i, &xhci_->irq_handles[i]);
    if (status != ZX_OK) {
      zxlogf(ERROR, "usb_xhci_bind map_interrupt failed %d", status);
      return status;
    }
  }

  // used for enabling bus mastering
  pci_.GetProto(&xhci_->pci);

  status = xhci_init(xhci_.get(), mode, irq_cnt);
  if (status != ZX_OK) {
    return status;
  }
  status = FinishBind();
  if (status != ZX_OK) {
    return status;
  }

  return ZX_OK;
}

zx_status_t UsbXhci::InitPdev() {
  zx_status_t status;

  fbl::AllocChecker ac;
  xhci_ = std::unique_ptr<xhci_t>(new (&ac) xhci_t);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  status = pdev_.GetBti(0, &xhci_->bti_handle);
  if (status != ZX_OK) {
    return status;
  }

  // TODO(voydanoff) find a C++ way to do this
  status = pdev_.MapMmio(PDEV_MMIO_INDEX, &xhci_->mmio);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: pdev_map_mmio failed", __func__);
    return status;
  }

  status = pdev_.GetInterrupt(PDEV_IRQ_INDEX, &xhci_->irq_handles[0]);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: pdev_map_interrupt failed", __func__);
    return status;
  }

  status = xhci_init(xhci_.get(), XHCI_PDEV, 1);
  if (status != ZX_OK) {
    return status;
  }
  status = FinishBind();
  if (status != ZX_OK) {
    return status;
  }

  return ZX_OK;
}

zx_status_t UsbXhci::Init() {
  if (pci_.is_valid()) {
    return InitPci();
  } else if (pdev_.is_valid()) {
    return InitPdev();
  } else if (composite_.is_valid()) {
    zx_device_t* pdev_device;
    size_t actual;

    // Retrieve platform device protocol from our first fragment.
    composite_.GetFragments(&pdev_device, 1, &actual);
    if (actual != 1) {
      return ZX_ERR_NOT_SUPPORTED;
    }
    pdev_ = pdev_device;
    if (!pdev_.is_valid()) {
      zxlogf(ERROR, "UsbXhci::Init: could not get platform device protocol");
      return ZX_ERR_NOT_SUPPORTED;
    }

    return InitPdev();
  } else {
    return ZX_ERR_NOT_SUPPORTED;
  }
}

zx_status_t UsbXhci::Create(void* ctx, zx_device_t* parent) {
  fbl::AllocChecker ac;
  auto dev = std::unique_ptr<UsbXhci>(new (&ac) UsbXhci(parent));
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  auto status = dev->Init();
  if (status != ZX_OK) {
    return status;
  }

  // devmgr is now in charge of the device.
  __UNUSED auto* dummy = dev.release();
  return ZX_OK;
}

static constexpr zx_driver_ops_t driver_ops = []() {
  zx_driver_ops_t ops = {};
  ops.version = DRIVER_OPS_VERSION;
  ops.bind = UsbXhci::Create;
  return ops;
}();

}  // namespace usb_xhci

// clang-format off
ZIRCON_DRIVER_BEGIN(usb_xhci, usb_xhci::driver_ops, "zircon", "0.1", 17)
    BI_GOTO_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_PDEV, 0),
    BI_GOTO_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_COMPOSITE, 1),

    // PCI binding support
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PCI),
    BI_ABORT_IF(NE, BIND_PCI_CLASS, 0x0C),
    BI_ABORT_IF(NE, BIND_PCI_SUBCLASS, 0x03),
    BI_MATCH_IF(EQ, BIND_PCI_INTERFACE, 0x30),
    BI_ABORT(),

    // platform bus support
    BI_LABEL(0),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_GENERIC),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_GENERIC),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_USB_XHCI),
    BI_ABORT(),

    // composite binding support
    BI_LABEL(1),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_GENERIC),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_GENERIC),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_USB_XHCI_COMPOSITE),

    BI_ABORT(),
ZIRCON_DRIVER_END(usb_xhci)
