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

#include <lib/ddk/binding_driver.h>
#include <lib/ddk/debug.h>
#include <lib/ddk/hw/arch_ops.h>
#include <lib/ddk/metadata.h>
#include <lib/ddk/platform-defs.h>
#include <lib/device-protocol/pci.h>
#include <lib/fit/defer.h>
#include <lib/fpromise/promise.h>
#include <lib/trace/event.h>
#include <lib/zx/bti.h>
#include <lib/zx/interrupt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <threads.h>
#include <unistd.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <algorithm>
#include <cstdint>
#include <memory>
#include <string>

#include <fbl/alloc_checker.h>
#include <usb/usb-request.h>

#include "src/devices/usb/drivers/xhci/registers.h"
#include "src/devices/usb/drivers/xhci/xhci-context.h"
#include "src/devices/usb/drivers/xhci/xhci-enumeration.h"

namespace usb_xhci {

namespace {

uint32_t kMicroframesPerFrame = 8;  // Per 3.2 spec, 1 frame is 1 ms, 1 microframe is 125 us.

// Obtains the slot index for a specified endpoint.
uint32_t Log2(uint32_t value) { return 31 - __builtin_clz(value); }

uint32_t RoundUp(uint32_t dividend, uint32_t divisor) { return 1 + (dividend - 1) / divisor; }

// Computes the interval value for a specified endpoint.
int ComputeInterval(const usb_endpoint_descriptor_t* ep, usb_speed_t speed) {
  uint8_t ep_type = ep->bm_attributes & USB_ENDPOINT_TYPE_MASK;
  uint8_t interval = ep->b_interval;
  if (ep_type == USB_ENDPOINT_CONTROL || ep_type == USB_ENDPOINT_BULK) {
    if (speed == USB_SPEED_HIGH) {
      interval = std::clamp(interval, static_cast<uint8_t>(1), static_cast<uint8_t>(16));
      return Log2(interval);
    } else {
      return 0;
    }
  }

  // now we deal with interrupt and isochronous endpoints
  // first make sure bInterval is in legal range
  // See table 6-12 in xHCI specification section 6.2.3.6
  if (ep_type == USB_ENDPOINT_INTERRUPT && (speed == USB_SPEED_LOW || speed == USB_SPEED_FULL)) {
    interval = static_cast<uint8_t>(std::clamp(static_cast<int>(interval), 1, 255));
  } else {
    interval = static_cast<uint8_t>(std::clamp(static_cast<int>(interval), 1, 16));
  }

  switch (speed) {
    case USB_SPEED_LOW:
      return Log2(interval) + 3;  // + 3 to convert 125us to 1ms
    case USB_SPEED_FULL:
      if (ep_type == USB_ENDPOINT_ISOCHRONOUS) {
        return (interval - 1) + 3;
      } else {
        return Log2(interval) + 3;
      }
    case USB_SPEED_SUPER:
    case USB_SPEED_HIGH:
      return interval - 1;
    default:
      return 0;
  }
}

}  // namespace

bool UsbXhci::Running() const { return running_; }

void UsbXhci::RingDoorbell(uint8_t slot, uint8_t target) {
  DOORBELL::Get(doorbell_offset_, slot).FromValue(0).set_Target(target).WriteTo(&mmio_.value());
}

uint16_t UsbXhci::InterrupterMapping() {
  // No inactive interrupters. Find one with least pressure.
  uint16_t idx = 0;
  size_t min_pressure = interrupter(0).ring().GetPressure();
  for (uint16_t i = 0; i < interrupters_.size(); i++) {
    if (!interrupter(i).active()) {
      continue;
    }
    size_t pressure = interrupter(i).ring().GetPressure();
    if (min_pressure < pressure) {
      idx = i;
      min_pressure = pressure;
    }
  }
  return idx;
}

fpromise::promise<void, zx_status_t> UsbXhci::Timeout(uint16_t target_interrupter,
                                                      zx::time deadline) {
  return interrupter(target_interrupter).Timeout(deadline);
}

fpromise::promise<void, zx_status_t> UsbXhci::DisableSlotCommand(uint32_t slot_id) {
  auto state = device_state_[slot_id - 1];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    // TODO(https://fxbug.dev/42067447): Use and test appropriate result status.
    return fpromise::make_error_promise<zx_status_t>(ZX_OK);
  }
  return DisableSlotCommand(*state);
}

fpromise::promise<void, zx_status_t> UsbXhci::DisableSlotCommand(DeviceState& state) {
  uint8_t port;
  bool connected_to_hub = false;
  {
    fbl::AutoLock _(&state.transaction_lock());
    if (!state.IsValid()) {
      zxlogf(ERROR, "DisableSlotCommand state is not valid");
      // TODO(https://fxbug.dev/42067447): Use and test appropriate result status.
      return fpromise::make_error_promise<zx_status_t>(ZX_OK);
    }
    state.Disconnect();
    port = state.GetPort();
    connected_to_hub = static_cast<bool>(state.GetHubLocked());
  }
  DisableSlot cmd;
  cmd.set_slot(state.GetSlot());
  auto context = command_ring_.AllocateContext();
  if (!context) {
    return fpromise::make_error_promise<zx_status_t>(ZX_ERR_BAD_STATE);
  }
  if (!connected_to_hub) {
    port_state_[port - 1].slot_id = 0;
  }

  return SubmitCommand(cmd, std::move(context))
      .then([this](fpromise::result<TRB*, zx_status_t>& result)
                -> fpromise::result<void, zx_status_t> {
        if (result.is_error()) {
          return fpromise::error(result.error());
        }
        TRB* trb = result.value();
        auto completion_event = reinterpret_cast<CommandCompletionEvent*>(trb);
        if (completion_event->CompletionCode() != CommandCompletionEvent::Success) {
          return fpromise::error(ZX_ERR_BAD_STATE);
        }
        dcbaa_[completion_event->SlotID()] = 0;
        return fpromise::ok();
      })
      .box();
}

TRBPromise UsbXhci::EnableSlotCommand() {
  TRB trb;
  Control::Get().FromValue(0).set_Type(Control::EnableSlot).ToTrb(&trb);
  auto context = command_ring_.AllocateContext();
  return SubmitCommand(trb, std::move(context));
}

fpromise::promise<OwnedRequest, void> UsbXhci::UsbHciRequestQueue(OwnedRequest usb_request) {
  fpromise::bridge<OwnedRequest, void> bridge;
  usb_request_complete_callback_t completion;
  completion.callback = [](void* ctx, usb_request_t* req) {
    auto completer = static_cast<fpromise::completer<OwnedRequest, void>*>(ctx);
    completer->complete_ok(OwnedRequest(req, sizeof(usb_request_t)));
    delete completer;
  };
  completion.ctx = new fpromise::completer<OwnedRequest, void>(std::move(bridge.completer));
  UsbHciRequestQueue(usb_request.take(), &completion);
  return bridge.consumer.promise().box();
}

TRBPromise UsbXhci::AddressDeviceCommand(uint8_t slot_id) {
  usb_xhci::AddressDeviceStruct cmd;
  cmd.set_BSR(0);
  cmd.set_SlotID(slot_id);
  return SubmitCommand(cmd, command_ring_.AllocateContext());
}

std::optional<usb_speed_t> UsbXhci::GetDeviceSpeed(uint8_t slot) {
  auto state = device_state_[slot - 1];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    return std::nullopt;
  }
  {
    fbl::AutoLock _(&state->transaction_lock());
    if (state->IsDisconnecting()) {
      return std::nullopt;
    }
    if (state->GetHubLocked()) {
      return state->GetHubLocked()->speed;
    }
  }
  return static_cast<usb_speed_t>(
      PORTSC::Get(cap_length_, state->GetPort()).ReadFrom(&mmio_.value()).PortSpeed());
}

usb_speed_t UsbXhci::GetPortSpeed(uint8_t port_id) const {
  return static_cast<usb_speed_t>(
      PORTSC::Get(cap_length_, port_id).ReadFrom(&mmio_.value()).PortSpeed());
}

TRBPromise UsbXhci::AddressDeviceCommand(uint8_t slot_id, uint8_t port_id,
                                         std::optional<HubInfo> hub_info, bool bsr) {
  auto state = device_state_[slot_id - 1];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    return fpromise::make_error_promise(ZX_ERR_IO_NOT_PRESENT);
  }
  return state->AddressDeviceCommand(this, slot_id, port_id, hub_info, dcbaa_, InterrupterMapping(),
                                     &command_ring_, &mmio_.value(), bsr);
}

void UsbXhci::SetDeviceInformation(uint8_t slot, uint8_t port, const std::optional<HubInfo>& hub) {
  auto state = fbl::MakeRefCounted<DeviceState>(slot - 1, this);
  fbl::AutoLock _(&state->transaction_lock());
  state->SetDeviceInformation(slot, port, hub);
  if (hub) {
    auto hub_state = hub->hub_state;
    // Here, the hub_state is expected to be different from the device's state,
    // otherwise a double-acquire occurs.
    ZX_ASSERT(hub_state != state);
    fbl::AutoLock _(&hub_state->transaction_lock());
    if (hub_state->IsDisconnecting()) {
      return;
    }
    hub_state->GetHubLocked()->port_to_device[port - 1] = static_cast<uint8_t>(slot - 1);
  }
  device_state_[slot - 1] = std::move(state);
}

TRBPromise UsbXhci::SetMaxPacketSizeCommand(uint8_t slot_id, uint8_t bMaxPacketSize0) {
  auto state = device_state_[slot_id - 1];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    return fpromise::make_error_promise(ZX_ERR_IO_NOT_PRESENT);
  }
  usb_xhci::AddressDeviceStruct cmd;
  {
    fbl::AutoLock _(&state->transaction_lock());
    if (state->IsDisconnecting()) {
      return fpromise::make_error_promise(ZX_ERR_IO_NOT_PRESENT);
    }
    auto control = reinterpret_cast<uint32_t*>(state->GetInputContext()->virt());
    auto endpoint_context = reinterpret_cast<EndpointContext*>(
        reinterpret_cast<unsigned char*>(control) + (slot_size_bytes_ * 2));
    endpoint_context->set_MAX_PACKET_SIZE(bMaxPacketSize0);
    Control::Get().FromValue(0).set_Type(Control::EvaluateContextCommand).ToTrb(&cmd);
    cmd.set_SlotID(slot_id);

    cmd.ptr = state->GetInputContext()->phys()[0];
  }
  auto context = command_ring_.AllocateContext();
  return SubmitCommand(cmd, std::move(context));
}

zx_status_t UsbXhci::DeviceOnline(uint32_t slot, uint16_t port, usb_speed_t speed) {
  bool is_usb_3 = false;
  zxlogf(DEBUG, "Device online. slot - %d port - %d", slot, port);
  {
    auto state = device_state_[slot - 1];
    if (!state) {
      zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
      return ZX_ERR_IO_NOT_PRESENT;
    }
    fbl::AutoLock transaction_lock(&state->transaction_lock());
    if (state->IsDisconnecting()) {
      return ZX_ERR_IO_NOT_PRESENT;
    }
    if (state->GetHubLocked()) {
      transaction_lock.release();
      PostCallback([=](const ddk::UsbBusInterfaceProtocolClient& bus) {
        uint32_t hub_id;
        {
          auto state = device_state_[slot - 1];
          if (!state) {
            zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
            return ZX_ERR_IO_NOT_PRESENT;
          }
          fbl::AutoLock _(&state->transaction_lock());
          if (state->IsDisconnecting()) {
            return ZX_ERR_IO_NOT_PRESENT;
          }
          if (!state->GetHubLocked()) {
            // Race condition -- device was unplugged before we got a chance to notify the bus
            // driver.
            return ZX_OK;
          }
          hub_id = SlotIdToDeviceId(state->GetHubLocked()->hub_state->GetSlot());
        }
        bus.AddDevice(slot - 1, hub_id, speed);
        return ZX_OK;
      });
      return ZX_OK;
    }
    is_usb_3 = GetPortState()[port].is_USB3;
  }
  PostCallback([=](const ddk::UsbBusInterfaceProtocolClient& bus) {
    bus.AddDevice(slot - 1,
                  static_cast<uint32_t>(is_usb_3 ? UsbHciGetMaxDeviceCount() - 1
                                                 : UsbHciGetMaxDeviceCount() - 2),
                  speed);
    return ZX_OK;
  });
  return ZX_OK;
}

fpromise::promise<void, zx_status_t> UsbXhci::DeviceOffline(uint32_t slot) {
  auto state = device_state_[slot - 1];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
  }
  {
    fbl::AutoLock _(&state->transaction_lock());
    if (state->IsDisconnecting()) {
      return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
    }
    state->Disconnect();
  }
  fpromise::bridge<void, zx_status_t> bridge;
  PostCallback([this, slot, cb = std::move(bridge.completer)](
                   const ddk::UsbBusInterfaceProtocolClient& bus) mutable {
    auto state = std::move(device_state_[slot - 1]);
    if (!state) {
      zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
      return ZX_ERR_IO_NOT_PRESENT;
    }
    for (uint8_t i = 0; i < kMaxEndpoints; i++) {
      fbl::AutoLock _(&state->transaction_lock());
      auto trbs = state->GetEndpoint(i).transfer_ring().TakePendingTRBs();
      for (auto& trb : trbs) {
        std::get<Request>(*trb.request).Complete(ZX_ERR_IO_NOT_PRESENT, 0);
      }
    }
    fbl::DoublyLinkedList<std::unique_ptr<TRBContext>> trbs;
    {
      fbl::AutoLock _(&state->transaction_lock());
      trbs = state->GetEndpoint().transfer_ring().TakePendingTRBs();
    }
    for (auto& trb : trbs) {
      std::get<Request>(*trb.request).Complete(ZX_ERR_IO_NOT_PRESENT, 0);
    }
    zx_status_t status = bus.RemoveDevice(slot - 1);
    if (status != ZX_OK) {
      cb.complete_error(status);
      return status;
    }
    cb.complete_ok();
    return status;
  });
  return bridge.consumer.promise().box();
}

void UsbXhci::CreateDeviceInspectNode(uint32_t slot, uint16_t vendor_id, uint16_t product_id) {
  auto state = device_state_[slot - 1];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    return;
  }

  char name[64];
  snprintf(name, sizeof(name), "Device %hu", slot);
  auto node = inspect_root_node().CreateChild(name);
  state->CreateInspectNode(std::move(node), vendor_id, product_id);
}

void UsbXhci::ResetPort(uint16_t port) {
  PORTSC sc = PORTSC::Get(cap_length_, port).ReadFrom(&mmio_.value());
  PORTSC::Get(cap_length_, port)
      .FromValue(0)
      .set_CCS(sc.CCS())
      .set_PortSpeed(sc.PortSpeed())
      .set_PIC(sc.PIC())
      .set_PLS(sc.PLS())
      .set_PP(sc.PP())
      .set_PR(1)
      .WriteTo(&mmio_.value());
}

fpromise::promise<void, zx_status_t> UsbXhci::UsbHciHubDeviceAddedAsync(uint32_t device_id,
                                                                        uint32_t port,
                                                                        usb_speed_t speed) {
  auto state = device_state_[device_id];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
  }
  // Acquire a slot
  HubInfo hub;
  {
    fbl::AutoLock _(&state->transaction_lock());
    hub.hub_state = state;
    hub.speed = speed;
    hub.parent_port_number = static_cast<uint8_t>(port);
    if (state->GetHubLocked()) {
      hub.multi_tt = state->GetHubLocked()->multi_tt;
      hub.route_string = (state->GetHubLocked()->route_string) |
                         ((port) << (state->GetHubLocked()->hub_depth * 4));
      hub.hub_depth = static_cast<uint8_t>(state->GetHubLocked()->hub_depth);
      hub.hub_speed = static_cast<uint8_t>(state->GetHubLocked()->speed);
      hub.rh_port = state->GetHubLocked()->rh_port;
      hub.tt_info = state->GetHubLocked()->tt_info;
    }
  }
  zxlogf(INFO,
         "Hub found: Speed: %d, Port: %d, Parent port:%d "
         "Route String:%d, Multi_tt:%d, Device ID:%d",
         hub.hub_speed, port, hub.parent_port_number, hub.route_string, hub.multi_tt, device_id);

  return EnumerateDevice(this, static_cast<uint8_t>(port), std::make_optional(hub));
}

fpromise::promise<void, zx_status_t> UsbXhci::ConfigureHubAsync(uint32_t device_id,
                                                                usb_speed_t speed,
                                                                const usb_hub_descriptor_t* desc,
                                                                bool multi_tt) {
  auto state = device_state_[device_id];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
  }
  HubInfo hub;
  struct AddressDeviceStruct cmd;
  std::unique_ptr<TRBContext> context;
  {
    fbl::AutoLock _(&state->transaction_lock());
    if (state->IsDisconnecting()) {
      return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
    }
    hub.hub_state = state;
    hub.speed = speed;
    hub.hub_speed = speed;
    hub.multi_tt = multi_tt;
    hub.rh_port = state->GetPort();
    if (state->GetHubLocked()) {
      hub.parent_port_number = state->GetHubLocked()->parent_port_number;
      hub.route_string = state->GetHubLocked()->route_string;
      hub.hub_depth = static_cast<uint8_t>(state->GetHubLocked()->hub_depth + 1);
      hub.rh_port = state->GetHubLocked()->rh_port;
      hub.tt_info = state->GetHubLocked()->tt_info;
    }
    state->GetHubLocked() = hub;
    uint8_t slot = state->GetSlot();
    // Initialize input slot context data structure (6.2.2) with 1 context entry
    // Set root hub port number to port number and context entries to 1
    auto control = static_cast<uint32_t*>(state->GetInputContext()->virt());
    // Evaluate slot context
    control[0] = 0;
    control[1] = 1;
    auto slot_context = reinterpret_cast<SlotContext*>(reinterpret_cast<unsigned char*>(control) +
                                                       slot_size_bytes_);
    slot_context->set_SPEED(speed)
        .set_MULTI_TT(multi_tt)
        .set_HUB(1)
        .set_PORT_COUNT(desc->b_nbr_ports)
        .set_TTT((speed == USB_SPEED_HIGH) ? ((desc->w_hub_characteristics >> 5) & 3) : 0);
    // Use ConfigureEndpointCommand according to sections 6.2.2.2 and 6.2.2.3.
    Control::Get().FromValue(0).set_Type(Control::ConfigureEndpointCommand).ToTrb(&cmd);
    cmd.set_SlotID(slot).set_BSR(0);
    cmd.ptr = state->GetInputContext()->phys()[0];
    hw_mb();
    context = command_ring_.AllocateContext();
  }
  return SubmitCommand(cmd, std::move(context))
      .and_then([=](TRB*& trb) -> fpromise::promise<void, zx_status_t> {
        auto completion = reinterpret_cast<CommandCompletionEvent*>(trb);
        if (completion->CompletionCode() != CommandCompletionEvent::Success) {
          zxlogf(ERROR, "Failed to configure endpoint: CompletionCode() == %u",
                 completion->CompletionCode());
          return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO);
        }
        if (speed != USB_SPEED_SUPER) {
          return fpromise::make_result_promise<void, zx_status_t>(fpromise::ok());
        }
        std::optional<usb::Request<void>> request_wrapper;
        zx_status_t status =
            usb::Request<void>::Alloc(&request_wrapper, 0, 0, UsbHciGetRequestSize());
        if (status != ZX_OK) {
          return fpromise::make_error_promise<zx_status_t>(status);
        }
        usb_request_t* request = request_wrapper->request();
        request->direct = true;
        request->header.device_id = device_id;
        request->header.ep_address = 0;
        request->setup.bm_request_type = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE;
        {
          fbl::AutoLock _(&state->transaction_lock());
          if (state->IsDisconnecting()) {
            return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
          }
          request->setup.w_value = state->GetHubLocked()->hub_depth;
        }
        request->setup.w_index = 0;
        request->setup.b_request = USB_HUB_SET_DEPTH;
        request->setup.w_length = 0;
        return UsbHciRequestQueue(std::move(*request_wrapper))
            .then(
                [](fpromise::result<OwnedRequest>& result) -> fpromise::result<void, zx_status_t> {
                  if (result.value().request()->response.status != ZX_OK) {
                    return fpromise::error(result.value().request()->response.status);
                  }
                  return fpromise::ok();
                });
      })
      .box();
}

void UsbXhci::DdkSuspend(ddk::SuspendTxn txn) {
  sync_completion_wait(&init_complete_, ZX_TIME_INFINITE);
  if (!mmio_.has_value()) {
    txn.Reply(ZX_ERR_BAD_STATE, 0);
    return;
  }
  // TODO(https://fxbug.dev/42118825): do different things based on the requested_state and suspend reason.
  // for now we shutdown the driver in preparation for mexec
  USBCMD::Get(cap_length_).ReadFrom(&mmio_.value()).set_ENABLE(0).WriteTo(&mmio_.value());
  while (!USBSTS::Get(cap_length_).ReadFrom(&mmio_.value()).HCHalted()) {
  }
  txn.Reply(ZX_OK, 0);
}

void UsbXhci::DdkUnbind(ddk::UnbindTxn txn) {
  // Prevent anything external to us from queueing any more work during shutdown.
  sync_completion_wait(&init_complete_, ZX_TIME_INFINITE);

  running_ = false;
  PostCallback([this, transaction = std::move(txn)](
                   const ddk::UsbBusInterfaceProtocolClient& client) mutable {
    ddk_interaction_loop_.Quit();
    USBCMD::Get(cap_length_).ReadFrom(&mmio_.value()).set_ENABLE(0).WriteTo(&mmio_.value());
    while (!USBSTS::Get(cap_length_).ReadFrom(&mmio_.value()).HCHalted()) {
    }
    // Disable all interrupters
    for (auto& it : interrupters_) {
      it.Stop();
    }
    // Should now be safe to terminate everything on the command ring
    bool pending;
    do {
      pending = false;
      auto trbs = command_ring_.TakePendingTRBs();
      for (auto& trb : trbs) {
        pending = true;
        CommandCompletionEvent evt;
        evt.ptr = 0;
        evt.set_Type(Control::CommandCompletionEvent);
        evt.set_CompletionCode(CommandCompletionEvent::CommandRingStopped);
        if (trb.completer.has_value()) {
          trb.completer.value().complete_ok(trb.trb);
        }
      }
      // Ensure that we've actually invoked the completions above
      // before moving to the next step.
      // TODO(https://fxbug.dev/42120782): Migrate to joins
      RunUntilIdle();
      for (size_t i = 0; i < max_slots_; i++) {
        auto state = device_state_[i];
        if (!state) {
          continue;
        }
        fbl::DoublyLinkedList<std::unique_ptr<TRBContext>> trbs;
        {
          fbl::AutoLock _(&state->transaction_lock());
          trbs = state->GetEndpoint().transfer_ring().TakePendingTRBs();
        }
        for (auto& trb : trbs) {
          pending = true;
          std::get<Request>(*trb.request).Complete(ZX_ERR_IO_NOT_PRESENT, 0);
        }
        for (uint8_t c = 0; c < 32; c++) {
          fbl::DoublyLinkedList<std::unique_ptr<TRBContext>> trbs;
          {
            fbl::AutoLock _(&state->transaction_lock());
            trbs = state->GetEndpoint(c).transfer_ring().TakePendingTRBs();
          }
          for (auto& trb : trbs) {
            pending = true;
            std::get<Request>(*trb.request).Complete(ZX_ERR_IO_NOT_PRESENT, 0);
          }
        }
      }
      // Flush any outstanding async I/O
      // TODO(https://fxbug.dev/42120782): Migrate to joins
      RunUntilIdle();
    } while (pending);

    for (auto& it : device_state_) {
      if (it) {
        // Reset HCI reference in device state so that HCI commands won't be issued.
        it->ResetHci();
      }
    }
    device_state_.reset();
    interrupters_.reset();
    transaction.Reply();
    return ZX_OK;
  });
}

void UsbXhci::DdkRelease() {
  int output;
  if (ddk_interaction_thread_.has_value()) {
    thrd_join(*ddk_interaction_thread_, &output);
  }
  if (init_thread_.has_value()) {
    thrd_join(*init_thread_, &output);
  }
  delete this;
}

// USB HCI protocol implementation.
void UsbXhci::UsbHciRequestQueue(usb_request_t* usb_request,
                                 const usb_request_complete_callback_t* complete_cb) {
  Request request(usb_request, *complete_cb, sizeof(usb_request_t));

  request.TraceFlow();

  if (request.request()->header.device_id >= params_.MaxSlots()) {
    request.Complete(ZX_ERR_INVALID_ARGS, 0);
    return;
  }
  auto state = device_state_[request.request()->header.device_id];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    request.Complete(ZX_ERR_IO_NOT_PRESENT, 0);
    return;
  }
  Endpoint* ep;
  uint8_t slot;
  uint8_t ep_addr = request.request()->header.ep_address;
  uint8_t index = static_cast<uint8_t>(XhciEndpointIndex(ep_addr) - 1);
  {
    fbl::AutoLock _(&state->transaction_lock());
    slot = state->GetSlot();
    if (!slot) {
      request.Complete(ZX_ERR_IO_NOT_PRESENT, 0);
      return;
    }
    if (unlikely(ep_addr == 0)) {
      ep = &state->GetEndpoint();
    } else {
      ep = &state->GetEndpoint(index);
    }
  }
  ep->QueueRequest(std::move(request));
  if (unlikely(ep_addr == 0)) {
    RingDoorbell(slot, 1);
  } else {
    RingDoorbell(slot, 2 + index);
  }
}

void UsbXhci::UsbHciSetBusInterface(const usb_bus_interface_protocol_t* bus_intf) {
  // We must be unbinding if the bus is currently valid.
  if (bus_.is_valid()) {
    // Assert that we've started unbinding and are no longer accepting
    // any requests to prevent a use-after-free situation.
    ZX_ASSERT(!running_);
    return;
  }
  ZX_ASSERT(bus_intf != nullptr);
  bus_ = bus_intf;
  sync_completion_signal(&bus_completion);
}
size_t UsbXhci::UsbHciGetMaxDeviceCount() {
  // Last two slots represent the virtual hubs (USB 2.0 and 3.0 respectively)
  return params_.MaxSlots() + 2;
}

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 (!ep_desc) {
    return ZX_ERR_INVALID_ARGS;
  }

  if (!running_) {
    return ZX_ERR_IO_NOT_PRESENT;
  }
  if (device_id >= params_.MaxSlots()) {
    // TODO: Root hub endpoint support
    return ZX_ERR_OUT_OF_RANGE;
  }
  if (!enable) {
    return RunSynchronously(kPrimaryInterrupter,
                            UsbHciDisableEndpoint(device_id, ep_desc, ss_com_desc));
  }
  return RunSynchronously(kPrimaryInterrupter,
                          UsbHciEnableEndpoint(device_id, ep_desc, ss_com_desc));
}

fpromise::promise<void, 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) {
  auto context = command_ring_.AllocateContext();
  auto state = device_state_[device_id];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
  }
  SlotContext* slot_context;
  TRB trb;
  uint32_t context_entries;
  uint8_t index;
  {
    fbl::AutoLock _(&state->transaction_lock());
    if (state->IsDisconnecting()) {
      return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
    }
    auto control = reinterpret_cast<uint32_t*>(state->GetInputContext()->virt());

    // Initialize input slot context data structure (6.2.2) with 1 context entry
    // Set root hub port number to port number and context entries to 1
    slot_context = reinterpret_cast<SlotContext*>(reinterpret_cast<unsigned char*>(control) +
                                                  slot_size_bytes_);
    context_entries = slot_context->CONTEXT_ENTRIES();
    index = XhciEndpointIndex(ep_desc->b_endpoint_address);
    if (index >= context_entries) {
      slot_context->set_CONTEXT_ENTRIES(index + 1);
    }
    // Allocate the transfer ring (see section 4.9)
    control[0] = 0;
    control[1] = 1 | (1 << (index + 1));
    zx_status_t status = state->InitEndpoint(
        ep_desc->b_endpoint_address, &this->interrupter(state->GetInterrupterTarget()).ring(),
        &mmio_.value());
    if (status != ZX_OK) {
      return fpromise::make_error_promise<zx_status_t>(status);
    }
    CRCR trb_phys = state->GetEndpoint(index - 1).transfer_ring().phys(cap_length_);
    // Initialize endpoint context 0
    // Set CERR to 3, TR dequeue pointer, max packet size, EP type = control, DCS = 1
    auto endpoint_context = reinterpret_cast<EndpointContext*>(
        reinterpret_cast<unsigned char*>(control) + (slot_size_bytes_ * (2 + index)));

    // See section 4.3.6
    uint32_t ep_type = ep_desc->bm_attributes & USB_ENDPOINT_TYPE_MASK;
    if (ep_type == USB_ENDPOINT_ISOCHRONOUS) {
      state->GetEndpoint(index - 1).transfer_ring().SetIsochronous();
    }
    uint32_t ep_index = ep_type;
    if ((ep_desc->b_endpoint_address & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN) {
      ep_index += 4;
    }
    endpoint_context->Init(static_cast<EndpointContext::EndpointType>(ep_index), trb_phys,
                           ep_desc->w_max_packet_size & 0x07FF);
    int interval = ComputeInterval(ep_desc, slot_context->SPEED());
    if (interval == -1) {
      interval = 1;
    }
    endpoint_context->set_Interval(interval);
    // Section 6.2.3.4
    uint32_t max_burst = 0;
    if (ss_com_desc) {
      max_burst = ss_com_desc->b_max_burst;
    } else {
      // TODO: Handle special case for interrupt/isochronous endpoints
      if ((slot_context->SPEED() == USB_SPEED_HIGH) && (ep_type == USB_ENDPOINT_ISOCHRONOUS)) {
        max_burst = (le16toh((ep_desc)->w_max_packet_size) >> 11) & 3;
      }
    }
    endpoint_context->set_MaxBurstSize(max_burst);
    if (ep_type == USB_ENDPOINT_ISOCHRONOUS) {
      endpoint_context->set_MAX_ESIT_PAYLOAD_LOW((ep_desc->w_max_packet_size & 0x07FF) *
                                                 (max_burst + 1));
    }
    trb.ptr = state->GetInputContext()->phys()[0];
    Control::Get()
        .FromValue((device_id + 1) << 24)
        .set_Type(Control::ConfigureEndpointCommand)
        .ToTrb(&trb);
  }
  // TODO(https://fxbug.dev/42109415): Implement async support
  hw_mb();
  return SubmitCommand(trb, std::move(context))
      .then(
          [=](fpromise::result<TRB*, zx_status_t>& result) -> fpromise::result<void, zx_status_t> {
            auto free_buffers = fit::defer([=]() {
              fbl::AutoLock _(&state->transaction_lock());
              state->GetEndpoint(index - 1).transfer_ring().Deinit();
              slot_context->set_CONTEXT_ENTRIES(context_entries);
            });
            if (result.is_error()) {
              return fpromise::error(result.error());
            }
            auto completion = static_cast<CommandCompletionEvent*>(result.value());
            if (completion->CompletionCode() == CommandCompletionEvent::BandwidthError) {
              // TODO(https://fxbug.dev/42068887): We could handle this by implementing bandwidth negotiation
              // (see Section 4.16.1). For now just return an error to the client.
              return fpromise::error(ZX_ERR_NO_RESOURCES);
            }
            if (completion->CompletionCode() != CommandCompletionEvent::Success) {
              zxlogf(ERROR, "Failed to configure endpoint: CompletionCode() == %u",
                     completion->CompletionCode());
              return fpromise::error(ZX_ERR_IO);
            }
            free_buffers.cancel();
            return fpromise::ok();
          })
      .box();
}

fpromise::promise<void, zx_status_t> UsbXhci::UsbHciDisableEndpoint(
    uint32_t device_id, const usb_endpoint_descriptor_t* ep_desc,
    const usb_ss_ep_comp_descriptor_t* ss_com_desc) {
  return UsbHciDisableEndpoint(device_id, ep_desc->b_endpoint_address);
}

fpromise::promise<void, zx_status_t> UsbXhci::UsbHciDisableEndpoint(uint32_t device_id,
                                                                    uint8_t ep_addr) {
  auto context = command_ring_.AllocateContext();
  auto state = device_state_[device_id];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
  }
  uint8_t index = XhciEndpointIndex(ep_addr);
  TRB trb;
  uint32_t* control;
  {
    fbl::AutoLock _(&state->transaction_lock());
    if (state->IsDisconnecting()) {
      return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
    }
    control = reinterpret_cast<uint32_t*>(state->GetInputContext()->virt());
    // Initialize input slot context data structure (6.2.2) with 1 context entry
    // Set root hub port number to port number and context entries to 1
    control[0] = (1 << (index + 1));
    control[1] = 1;
    trb.ptr = state->GetInputContext()->phys()[0];
    Control::Get()
        .FromValue((device_id + 1) << 24)
        .set_Type(Control::ConfigureEndpointCommand)
        .ToTrb(&trb);
  }
  // TODO(https://fxbug.dev/42109415): Implement async support
  hw_mb();
  return SubmitCommand(trb, std::move(context))
      .then(
          [=](fpromise::result<TRB*, zx_status_t>& result) -> fpromise::result<void, zx_status_t> {
            if (result.is_error()) {
              return fpromise::error(ZX_ERR_BAD_STATE);
            }
            auto completion = reinterpret_cast<CommandCompletionEvent*>(result.value());
            if (completion->CompletionCode() != CommandCompletionEvent::Success) {
              zxlogf(ERROR, "Failed to configure endpoint: CompletionCode() == %u",
                     completion->CompletionCode());
              return fpromise::error(ZX_ERR_BAD_STATE);
            }
            auto endpoint_context = reinterpret_cast<EndpointContext*>(
                reinterpret_cast<unsigned char*>(control) + (slot_size_bytes_ * (2 + index)));
            endpoint_context->Deinit();
            fbl::AutoLock _(&state->transaction_lock());
            if (state->IsDisconnecting()) {
              return fpromise::error(ZX_ERR_IO_NOT_PRESENT);
            }
            zx_status_t status = state->GetEndpoint(index - 1).transfer_ring().Deinit();
            // If we can't deinit the ring something is seriously wrong.
            if (status != ZX_OK) {
              return fpromise::error(ZX_ERR_BAD_STATE);
            }
            return fpromise::ok();
          })
      .box();
}

uint64_t UsbXhci::UsbHciGetCurrentFrame() {
  if (!running_) {
    return 0;
  }

  // Locking the logic below is important; without the lock, race conditions
  // were observed which led to "phantom" wraps being incorrectly counted.
  static fbl::Mutex lock;
  fbl::AutoLock _(&lock);

  uint32_t mfindex = MFINDEX::Get(runtime_offset_).ReadFrom(&mmio_.value()).INDEX();
  if (mfindex < last_mfindex_) {
    // Wrapped
    wrap_count_++;
  }

  last_mfindex_ = mfindex;
  uint64_t wrap_count = wrap_count_;
  // add IST + 1 to get next valid frame. spec 4.11.2.5
  // shift three to convert from 125us microframes to 1ms frames
  return (((wrap_count * (1 << 14)) + mfindex) >> 3) + ist_frames_ + 1;
}

zx_status_t UsbXhci::UsbHciConfigureHub(uint32_t device_id, usb_speed_t speed,
                                        const usb_hub_descriptor_t* desc, bool multi_tt) {
  if (!running_) {
    return ZX_ERR_IO_NOT_PRESENT;
  }
  sync_completion_t completion;
  zx_status_t hub_status = ZX_OK;
  ScheduleTask(kPrimaryInterrupter, ConfigureHubAsync(device_id, speed, desc, multi_tt)
                                        .then([&](fpromise::result<void, zx_status_t>& result) {
                                          if (result.is_ok()) {
                                            hub_status = ZX_OK;
                                          } else {
                                            hub_status = result.error();
                                          }
                                          sync_completion_signal(&completion);
                                          return result;
                                        })
                                        .box());
  sync_completion_wait(&completion, ZX_TIME_INFINITE);
  return hub_status;
}
zx_status_t UsbXhci::UsbHciHubDeviceAdded(uint32_t device_id, uint32_t port, usb_speed_t speed) {
  if (!running_) {
    return ZX_ERR_IO_NOT_PRESENT;
  }
  sync_completion_t completion;
  zx_status_t out_status;
  ScheduleTask(kPrimaryInterrupter, UsbHciHubDeviceAddedAsync(device_id, port, speed)
                                        .then([&](fpromise::result<void, zx_status_t>& result) {
                                          if (result.is_ok()) {
                                            out_status = ZX_OK;
                                          } else {
                                            out_status = result.error();
                                          }
                                          sync_completion_signal(&completion);
                                          return result;
                                        })
                                        .box());
  sync_completion_wait(&completion, ZX_TIME_INFINITE);
  return out_status;
}

zx_status_t UsbXhci::UsbHciHubDeviceRemoved(uint32_t hub_id, uint32_t port) {
  if (!running_) {
    return ZX_ERR_IO_NOT_PRESENT;
  }
  auto hub_state = device_state_[hub_id];
  if (!hub_state) {
    zxlogf(ERROR, "%s expects that slot is in use. hub_state should not be nullptr", __func__);
    return ZX_ERR_IO_NOT_PRESENT;
  }
  uint32_t device_id;
  {
    fbl::AutoLock _(&hub_state->transaction_lock());
    // In the case where the hub itself is unplugged,
    // we will likely have torn down the hub state
    // prior to teardown of devices connected to said hub.
    // If this is the case, just return OK.
    // Teardown of child devices will complete asynchronously
    if (!hub_state->GetHubLocked()) {
      return ZX_OK;
    }
    device_id = hub_state->GetHubLocked()->port_to_device[port - 1];
  }
  auto device_state = std::move(device_state_[device_id]);
  if (!device_state) {
    zxlogf(ERROR, "%s expects that slot is in use. device_state should not be nullptr", __func__);
    return ZX_ERR_IO_NOT_PRESENT;
  }
  {
    fbl::AutoLock _(&device_state->transaction_lock());
    device_state->Disconnect();
  }
  for (uint8_t i = 0; i < 32; i++) {
    fbl::DoublyLinkedList<std::unique_ptr<TRBContext>> trbs;
    {
      fbl::AutoLock _(&device_state->transaction_lock());
      trbs = device_state->GetEndpoint(i).transfer_ring().TakePendingTRBs();
    }
    for (auto& trb : trbs) {
      std::get<Request>(*trb.request).Complete(ZX_ERR_IO_NOT_PRESENT, 0);
    }
  }
  RunUntilIdle();
  fbl::DoublyLinkedList<std::unique_ptr<TRBContext>> trbs;
  {
    fbl::AutoLock _(&device_state->transaction_lock());
    trbs = device_state->GetEndpoint().transfer_ring().TakePendingTRBs();
  }
  for (auto& trb : trbs) {
    std::get<Request>(*trb.request).Complete(ZX_ERR_IO_NOT_PRESENT, 0);
  }
  RunUntilIdle();
  // Bus should always be valid since we're getting a callback from a hub
  // that is a child of the bus.
  ZX_ASSERT(bus_.is_valid());
  zx_status_t status = bus_.RemoveDevice(device_state->GetSlot() - 1);
  if (status != ZX_OK) {
    return status;
  }
  return ZX_OK;
}

zx_status_t UsbXhci::UsbHciHubDeviceReset(uint32_t device_id, uint32_t port) {
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t UsbXhci::UsbHciResetEndpoint(uint32_t device_id, uint8_t ep_address) {
  return RunSynchronously(kPrimaryInterrupter, UsbHciResetEndpointAsync(device_id, ep_address));
}

fpromise::promise<void, zx_status_t> UsbXhci::UsbHciResetEndpointAsync(uint32_t device_id,
                                                                       uint8_t ep_address) {
  if (device_id >= params_.MaxSlots()) {
    return fpromise::make_error_promise<zx_status_t>(ZX_ERR_NOT_SUPPORTED);
  }
  auto state = device_state_[device_id];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
  }
  ResetEndpoint reset_command;
  {
    fbl::AutoLock _(&state->transaction_lock());
    if (state->IsDisconnecting()) {
      return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
    }
    reset_command.set_ENDPOINT(XhciEndpointIndex(ep_address) + 1);
    reset_command.set_SLOT(state->GetSlot());
  }
  auto context = command_ring_.AllocateContext();
  if (!context) {
    return fpromise::make_error_promise<zx_status_t>(ZX_ERR_NO_MEMORY);
  }

  TransferRing* ring;
  {
    fbl::AutoLock l(&state->transaction_lock());
    if (ep_address == 0) {
      ring = &state->GetEndpoint().transfer_ring();
    } else {
      ring = &state->GetEndpoint(XhciEndpointIndex(ep_address) - 1).transfer_ring();
    }
    if (!ring->stalled()) {
      return fpromise::make_error_promise<zx_status_t>(ZX_ERR_INVALID_ARGS);
    }
  }
  return SubmitCommand(reset_command, std::move(context))
      .and_then([=](TRB*& trb) -> TRBPromise {
        CommandCompletionEvent* evt = static_cast<CommandCompletionEvent*>(trb);
        if (evt->CompletionCode() != CommandCompletionEvent::Success) {
          return fpromise::make_error_promise(ZX_ERR_IO);
        }

        SetTRDequeuePointer cmd;
        cmd.set_ENDPOINT(XhciEndpointIndex(ep_address) + 1);
        cmd.set_SLOT(state->GetSlot());
        auto res = ring->PeekCommandRingControlRegister(CapLength());
        if (res.is_error()) {
          return fpromise::make_error_promise(res.error_value());
        }
        cmd.SetPtr(res.value());
        auto context = command_ring_.AllocateContext();
        return SubmitCommand(cmd, std::move(context))
            .and_then([=](TRB*& result) {
              CommandCompletionEvent* evt = static_cast<CommandCompletionEvent*>(result);
              if (evt->CompletionCode() != CommandCompletionEvent::Success) {
                return fpromise::make_error_promise(ZX_ERR_IO);
              }
              fbl::AutoLock l(&state->transaction_lock());
              ring->set_stall(false);
              return fpromise::make_ok_promise(result);
            })
            .box();
      })
      .discard_value()
      .box();
}

// TODO(https://fxbug.dev/42109966): Either decide what these reset methods should do,
// or get rid of them.
zx_status_t UsbXhci::UsbHciResetDevice(uint32_t hub_address, uint32_t device_id) {
  return ZX_ERR_NOT_SUPPORTED;
}

size_t UsbXhci::UsbHciGetMaxTransferSize(uint32_t device_id, uint8_t ep_address) {
  if (device_id >= params_.MaxSlots()) {
    // TODO: Root hub endpoint support
    return 0;
  }
  auto state = device_state_[device_id];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    return 0;
  }

  fbl::AutoLock _(&state->transaction_lock());
  if (state->IsDisconnecting()) {
    return 0;
  }
  return SIZE_MAX;
}

zx_status_t UsbXhci::UsbHciCancelAll(uint32_t device_id, uint8_t ep_address) {
  if (!running_) {
    return ZX_ERR_IO_NOT_PRESENT;
  }
  return RunSynchronously(kPrimaryInterrupter, UsbHciCancelAllAsync(device_id, ep_address));
}

fpromise::promise<void, zx_status_t> UsbXhci::UsbHciCancelAllAsync(uint32_t device_id,
                                                                   uint8_t ep_address) {
  auto state = device_state_[device_id];
  if (!state) {
    return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
  }

  StopEndpoint stop;
  {
    fbl::AutoLock state_lock(&state->transaction_lock());
    if (state->IsDisconnecting()) {
      return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
    }
    uint8_t index = static_cast<uint8_t>(XhciEndpointIndex(ep_address) + 1);
    stop.set_ENDPOINT(index);
    stop.set_SLOT(state->GetSlot());
  }
  auto context = command_ring_.AllocateContext();
  return SubmitCommand(stop, std::move(context))
      .and_then([=](TRB*& trb) -> fpromise::promise<void, zx_status_t> {
        auto completion_event = static_cast<CommandCompletionEvent*>(trb);
        auto completion_code = completion_event->CompletionCode();
        zx_status_t status =
            (completion_code == CommandCompletionEvent::Success) ? ZX_OK : ZX_ERR_IO;
        if (status != ZX_OK) {
          return fpromise::make_error_promise<zx_status_t>(status);
        }
        // We can now move everything off of the transfer ring starting at the dequeue pointer
        uint8_t index;
        fbl::DoublyLinkedList<std::unique_ptr<TRBContext>> trbs;
        zx_paddr_t new_ptr_phys = 0;
        {
          TRB* new_ptr = nullptr;
          fbl::AutoLock _(&state->transaction_lock());
          if (state->IsDisconnecting()) {
            return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
          }
          index = static_cast<uint8_t>(XhciEndpointIndex(ep_address) - 1);
          auto& transfer_ring = state->GetEndpoint(index).transfer_ring();
          if (!transfer_ring.active()) {
            return fpromise::make_error_promise<zx_status_t>(ZX_ERR_IO_NOT_PRESENT);
          }
          trbs = transfer_ring.TakePendingTRBs();
          for (auto& trb : trbs) {
            new_ptr = trb.trb;
            auto control = Control::FromTRB(trb.trb);
            control.set_Cycle(!control.Cycle());
          }
          if (new_ptr) {
            new_ptr_phys = transfer_ring.VirtToPhys(new_ptr + 1);
          }
        }
        for (auto& trb : trbs) {
          std::get<Request>(*trb.request).Complete(ZX_ERR_CANCELED, 0);
        }

        if (!new_ptr_phys) {
          return fpromise::make_result_promise<void, zx_status_t>(fpromise::ok());
        }

        // It's possible that the dequeue pointer was in the middle of a multi-TRB TD when we
        // stopped. If this is the case, we need to adjust the dequeue pointer to point to the
        // index of the first TRB that we know about.
        SetTRDequeuePointer cmd;
        cmd.set_ENDPOINT(index + 2);
        cmd.set_SLOT(state->GetSlot());
        cmd.ptr = new_ptr_phys;
        auto context = command_ring_.AllocateContext();
        return SubmitCommand(cmd, std::move(context))
            .and_then([=](TRB*& trb) -> fpromise::result<void, zx_status_t> {
              auto completion_event = static_cast<CommandCompletionEvent*>(trb);
              auto completion_code = completion_event->CompletionCode();
              bool command_success = completion_code == CommandCompletionEvent::Success;
              zx_status_t status = command_success ? ZX_OK : ZX_ERR_IO;
              if (status != ZX_OK) {
                return fpromise::error(status);
              }
              return fpromise::ok();
            });
      })
      .box();
}

size_t UsbXhci::UsbHciGetRequestSize() { return Request::RequestSize(sizeof(usb_request_t)); }

void UsbXhci::Shutdown(zx_status_t status) {
  USBCMD::Get(cap_length_).ReadFrom(&mmio_.value()).set_ENABLE(0).WriteTo(&mmio_.value());
  while (!USBSTS::Get(cap_length_).ReadFrom(&mmio_.value()).HCHalted()) {
  }
  if (status != ZX_OK) {
    // If we're shutting down due to an error (not just regular unbind)
    // ensure that we remove the device.
    zxlogf(ERROR, "Internal xhci error, shutting down with error: %s",
           zx_status_get_string(status));
    DdkAsyncRemove();
  }
}

zx_status_t UsbXhci::InitQuirks() {
  fuchsia_hardware_pci::wire::DeviceInfo info;
  auto status = pci_.GetDeviceInfo(&info);
  if (status == ZX_ERR_PEER_CLOSED) {
    // Reset.
    pci_ = {};
  }
  if (status != ZX_OK) {
    return status;
  }
  if ((info.vendor_id == 0x1033) && (info.device_id == 0x194)) {
    qemu_quirk_ = true;
  }
  if ((info.vendor_id) == 0x8086 && (info.device_id == 0x8C31)) {
    // TODO(bbosak): Implement stub EHCI driver so we can properly
    // do the handoff in case the BIOS is managing a device on EHCI.
    // Quirk for some older Intel chipsets
    // Switch ports from EHCI to XHCI.
    uint32_t ports_available;
    pci_.ReadConfig32(0xdc, &ports_available);
    if (ports_available) {
      pci_.WriteConfig32(0xd8, ports_available);
    }
    // Route power and data lines for USB 2.0 ports
    pci_.ReadConfig32(0xd4, &ports_available);
    if (ports_available) {
      pci_.WriteConfig32(0xD0, ports_available);
    }
    // Handoff takes 5 seconds if we're contending with the EHCI controller.
    // (have to wait for enumeration to time out)
    sleep(5);
  }

  return ZX_OK;
}

zx_status_t UsbXhci::InitPci() {
  // Perform vendor-specific workarounds.
  auto status = InitQuirks();
  if (status != ZX_OK) {
    return status;
  }
  // PCIe interface supports cache snooping
  has_coherent_cache_ = true;
  // Initialize MMIO
  std::optional<fdf::MmioBuffer> buffer;
  status = pci_.MapMmio(0, ZX_CACHE_POLICY_UNCACHED_DEVICE, &buffer);
  if (status != ZX_OK) {
    return status;
  }
  mmio_ = std::move(*buffer);
  irq_count_ =
      std::min(kMaxInterrupters,
               static_cast<uint16_t>(HCSPARAMS1::Get().ReadFrom(&mmio_.value()).MaxIntrs()));

  // Make sure irq_count_ doesn't exceed supported max PCI IRQs.
  fuchsia_hardware_pci::wire::InterruptModes modes{};
  pci_.GetInterruptModes(&modes);
  uint32_t mode_irq_max = std::max(static_cast<uint16_t>(modes.msi_count), modes.msix_count);
  irq_count_ = std::min(irq_count_, static_cast<uint16_t>(mode_irq_max));
  status = pci_.ConfigureInterruptMode(irq_count_, /*out_mode=*/nullptr);
  if (status != ZX_OK) {
    return status;
  }
  fbl::AllocChecker ac;
  interrupters_ = fbl::MakeArray<Interrupter>(&ac, irq_count_);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }
  for (uint16_t i = 0; i < irq_count_; i++) {
    status = pci_.MapInterrupt(i, &interrupter(i).GetIrq());
    if (status != ZX_OK) {
      return status;
    }
  }
  status = pci_.SetBusMastering(true);
  if (status != ZX_OK) {
    return status;
  }
  return ZX_OK;
}

zx_status_t UsbXhci::InitMmio() {
  zx_status_t status;
  if (!pdev_.is_valid()) {
    return ZX_ERR_IO_INVALID;
  }
  std::optional<fdf::MmioBuffer> mmio;
  status = pdev_.MapMmio(0, &mmio);
  if (status != ZX_OK) {
    zxlogf(ERROR, "UsbXhci: failed to map MMIO registers (%s)", zx_status_get_string(status));
    return status;
  }
  mmio_ = std::move(*mmio);
  irq_count_ = static_cast<uint16_t>(HCSPARAMS1::Get().ReadFrom(&mmio_.value()).MaxIntrs());
  fbl::AllocChecker ac;
  interrupters_ = fbl::MakeArray<Interrupter>(&ac, irq_count_);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }
  for (uint16_t i = 0; i < irq_count_; i++) {
    status = pdev_.GetInterrupt(i, 0, &interrupter(i).GetIrq());
    if (status != ZX_OK) {
      zxlogf(ERROR, "UsbXhci: failed fetch interrupt (%s)", zx_status_get_string(status));
      return status;
    }
  }
  return ZX_OK;
}

void UsbXhci::ParseSupportedProtocol() {
  HCCPARAMS1 hcc = HCCPARAMS1::Get().ReadFrom(&mmio_.value());
  if (hcc.ReadFrom(&mmio_.value()).xECP()) {
    XECP current = XECP::Get(hcc).ReadFrom(&mmio_.value());
    while (true) {
      if (current.ID() == XECP::SupportedProtocol) {
        auto word0 = CapabilityRegWord0::Get(current).ReadFrom(&mmio_.value());
        auto word2 = CapabilityRegWord2::Get(current).ReadFrom(&mmio_.value());

        zxlogf(DEBUG, "Supported protocol info: Revision:%d:%d USB%d port offset %d port count %d",
               word0.MAJOR_REVISION(), word0.MINOR_REVISION(), word0.MAJOR_REVISION(),
               word2.PortOffset(), word2.PortCount());
      }
      if (!current.NEXT()) {
        break;
      }
      current = current.Next().ReadFrom(&mmio_.value());
    }
  }
}

void UsbXhci::BiosHandoff() {
  HCCPARAMS1 hcc = HCCPARAMS1::Get().ReadFrom(&mmio_.value());
  if (hcc.ReadFrom(&mmio_.value()).xECP()) {
    XECP current = XECP::Get(hcc).ReadFrom(&mmio_.value());
    while (true) {
      if (current.ID() == XECP::UsbLegacySupport) {
        // Check is BIOS owns the host controller. If so, signal BIOS.
        if (current.reg_value() & kBiosOwned) {
          current.set_reg_value(current.reg_value() | kOSOwned).WriteTo(&mmio_.value());

          // Wait for control transfer.
          current = current.ReadFrom(&mmio_.value());
          while (current.reg_value() & kBiosOwned) {
            current = current.ReadFrom(&mmio_.value());
            usleep(10);
          };
        }
      }
      if (!current.NEXT()) {
        break;
      }
      current = current.Next().ReadFrom(&mmio_.value());
    }
  }
}

void UsbXhci::ResetController() {
  USBCMD::Get(cap_length_).ReadFrom(&mmio_.value()).set_ENABLE(0).WriteTo(&mmio_.value());
  while (!USBSTS::Get(cap_length_).ReadFrom(&mmio_.value()).HCHalted()) {
    zx::nanosleep(zx::deadline_after(zx::msec(1)));
  }
  while (USBSTS::Get(cap_length_).ReadFrom(&mmio_.value()).CNR()) {
    zx::nanosleep(zx::deadline_after(zx::msec(1)));
  }
  USBCMD::Get(cap_length_).ReadFrom(&mmio_.value()).set_RESET(1).WriteTo(&mmio_.value());
  while (USBCMD::Get(cap_length_).ReadFrom(&mmio_.value()).RESET()) {
    zx::nanosleep(zx::deadline_after(zx::msec(1)));
  }
  while (USBSTS::Get(cap_length_).ReadFrom(&mmio_.value()).CNR()) {
    zx::nanosleep(zx::deadline_after(zx::msec(1)));
  }
}

int UsbXhci::InitThread() {
  ZX_ASSERT(init_txn_.has_value());  // This is set in DdkInit before creating this thread.
  auto call = fit::defer([=]() { init_txn_->Reply(ZX_ERR_INTERNAL); });
  auto init_completer = fit::defer([=]() { sync_completion_signal(&init_complete_); });
  // Initialize either the PCI or MMIO structures first
  zx_status_t status;
  if (pci_.is_valid()) {
    status = InitPci();
    if (status != ZX_ERR_PEER_CLOSED && status != ZX_OK) {
      zxlogf(ERROR, "PCI initialization failed with: %s", zx_status_get_string(status));
      return thrd_error;
    }
  }
  // Because pci_.is_valid() may have changed in InitQuirks().
  if (!pci_.is_valid()) {
    status = InitMmio();
    if (status != ZX_OK) {
      zxlogf(ERROR, "MMIO initialization failed with: %s", zx_status_get_string(status));
      return thrd_error;
    }
  }
  // Perform the BIOS handoff if necessary
  BiosHandoff();

  // Read Supported Protocol Capabilities if available.
  ParseSupportedProtocol();

  // At startup the device is in an unknown state
  // Reset the xHCI to place everything in its well-defined
  // initial state.
  uint8_t cap_length = CapLength::Get().ReadFrom(&mmio_.value()).Length();
  cap_length_ = cap_length;
  // Perform xHCI reset process
  ResetController();
  // Start DDK interaction thread
  thrd_t thrd;
  int thread_status = thrd_create_with_name(
      &thrd,
      [](void* ctx) -> int {
        auto hci = static_cast<UsbXhci*>(ctx);
        hci->ddk_interaction_loop_.Run();
        return thrd_success;
      },
      this, "ddk_interaction_thread");
  if (thread_status != thrd_success) {
    return thread_status;
  }
  ddk_interaction_thread_ = thrd;
  // Finish HCI initialization
  status = HciFinalize();
  if (status != ZX_OK) {
    zxlogf(ERROR, "xHCI initialization failed with %s", zx_status_get_string(status));
    return thrd_error;
  }
  // If |HciFinalize| succeeded, it would have replied to |init_txn_| and made the device visible.
  call.cancel();
  return thrd_success;
}

zx_status_t UsbXhci::HciFinalize() {
  hcc_ = HCCPARAMS1::Get().ReadFrom(&mmio_.value());
  HCSPARAMS1 hcsparams1 = HCSPARAMS1::Get().ReadFrom(&mmio_.value());

  // Initialize Inspect values
  HciVersion hci_version = HciVersion::Get().ReadFrom(&mmio_.value());
  inspect_.Init(hci_version.reg_value(), hcsparams1, hcc_);

  // Reset Warm Reset Change (WRC) bit if necessary (see Table 5-27, bit 19 in Section 5.4.8,
  // xHCI specification). This is done to acknowledge any warm reset done during bootup.
  for (uint16_t i = 0; i < hcsparams1.MaxPorts(); i++) {
    auto sc = PORTSC::Get(cap_length_, i + 1).ReadFrom(&mmio_.value());
    if (sc.WRC()) {
      sc.set_WRC(sc.WRC()).WriteTo(&mmio_.value());
    }
  }

  zx_status_t status;
  is_32bit_ = !hcc_.AC64();
  params_ = hcsparams1;
  CONFIG::Get(cap_length_)
      .ReadFrom(&mmio_.value())
      .set_MaxSlotsEn(hcsparams1.MaxSlots())
      .WriteTo(&mmio_.value());
  {
    zx::bti bti;
    if (pci_.is_valid()) {
      if (status = pci_.GetBti(0, &bti); status != ZX_OK) {
        zxlogf(ERROR, "pci_.GetBti(): %s", zx_status_get_string(status));
        return ZX_ERR_INTERNAL;
      }
    } else {
      if (status = pdev_.GetBti(0, &bti); status != ZX_OK) {
        zxlogf(ERROR, "pdev_.GetBti(): %s", zx_status_get_string(status));
        return ZX_ERR_INTERNAL;
      }
    }
    bti_ = std::move(bti);
  }
  uint32_t page_size = USB_PAGESIZE::Get(cap_length_).ReadFrom(&mmio_.value()).PageSize() << 12;
  page_size_ = page_size;
  // TODO(bbosak): Correct this to use variable alignment when we get kernel
  // support for this.
  if (page_size != zx_system_get_page_size()) {
    zxlogf(ERROR, "xHC page size differs from platform page size");
    return ZX_ERR_INTERNAL;
  }
  uint32_t align_log2 = 0;

  status = buffer_factory_->CreatePaged(bti_, zx_system_get_page_size(), false, &dcbaa_buffer_);
  if (status != ZX_OK) {
    zxlogf(ERROR, "buffer_factory_->CreatePaged(): %s", zx_status_get_string(status));
    return ZX_ERR_INTERNAL;
  }
  if (is_32bit_ && (dcbaa_buffer_->phys()[0] >= UINT32_MAX)) {
    zxlogf(ERROR, "xHC using 32bit mode but dcbaa buffer address overflows 32bits");
    return ZX_ERR_INTERNAL;
  }
  dcbaa_ = static_cast<uint64_t*>(dcbaa_buffer_->virt());
  fbl::AllocChecker ac;
  HCSPARAMS2 hcsparams2 = HCSPARAMS2::Get().ReadFrom(&mmio_.value());
  auto ist = hcsparams2.IST();
  ist_frames_ = (ist & 0x8) ? /* frames */ (ist & 0x7)
                            : /* microframes */ RoundUp(ist & 0x7, kMicroframesPerFrame);
  RuntimeRegisterOffset offset = RuntimeRegisterOffset::Get().ReadFrom(&mmio_.value());
  runtime_offset_ = offset;
  uint32_t buffers = hcsparams2.MAX_SCRATCHPAD_BUFFERS_LOW() |
                     ((hcsparams2.MAX_SCRATCHPAD_BUFFERS_HIGH() << 5) + 1);
  scratchpad_buffers_ = fbl::MakeArray<std::unique_ptr<dma_buffer::ContiguousBuffer>>(&ac, buffers);
  if (!ac.check()) {
    zxlogf(ERROR, "fbl::MakeArray<std::unique_ptr<dma_buffer::ContiguousBuffer>> allocation fails");
    return ZX_ERR_NO_MEMORY;
  }
  if (fbl::round_up(buffers * sizeof(uint64_t), zx_system_get_page_size()) >
      zx_system_get_page_size()) {
    // We can't create multi-page contiguously physical uncached buffers.
    // This is presently not supported in the kernel.
    zxlogf(ERROR, "physically-contiguous buffer exceeds system pagesize");
    return ZX_ERR_NOT_SUPPORTED;
  }
  if (buffer_factory_->CreatePaged(bti_, zx_system_get_page_size(), false,
                                   &scratchpad_buffer_array_) != ZX_OK) {
    zxlogf(ERROR, "buffer_factory_->CreateContiguous(buffer[0]): %s", zx_status_get_string(status));
    return ZX_ERR_INTERNAL;
  }
  if (is_32bit_ && (scratchpad_buffer_array_->phys()[0] >= UINT32_MAX)) {
    zxlogf(ERROR, "xHC using 32bit mode but scratchpad buffer[0] address overflows 32bits");
    return ZX_ERR_INTERNAL;
  }
  uint64_t* scratchpad_buffer_array = static_cast<uint64_t*>(scratchpad_buffer_array_->virt());
  for (size_t i = 0; i < buffers - 1; i++) {
    status =
        buffer_factory_->CreateContiguous(bti_, page_size, align_log2, &scratchpad_buffers_[i]);
    if (status != ZX_OK) {
      zxlogf(ERROR, "buffer_factory_->CreateContiguous(buffer[%zu]): %s", i,
             zx_status_get_string(status));
      return ZX_ERR_INTERNAL;
    }
    if (is_32bit_ && (scratchpad_buffers_[i]->phys() >= UINT32_MAX)) {
      zxlogf(ERROR, "xHC using 32bit mode but scratchpad buffer[%zu] address overflows 32bits", i);
      return ZX_ERR_INTERNAL;
    }
    scratchpad_buffer_array[i] = scratchpad_buffers_[i]->phys();
  }
  static_cast<uint64_t*>(dcbaa_buffer_->virt())[0] = scratchpad_buffer_array_->phys()[0];
  max_slots_ = hcsparams1.MaxSlots();
  slot_size_bytes_ = hcc_.CSZ() == 1 ? 64 : 32;
  device_state_ = fbl::MakeArray<fbl::RefPtr<DeviceState>>(&ac, max_slots_);
  if (!ac.check()) {
    zxlogf(ERROR, "fbl::MakeArray<DeviceState> allocation fails");
    return ZX_ERR_NO_MEMORY;
  }
  port_state_ = fbl::MakeArray<PortState>(&ac, hcsparams1.MaxPorts());
  if (!ac.check()) {
    zxlogf(ERROR, "fbl::MakeArray<PortState> allocation fails");
    return ZX_ERR_NO_MEMORY;
  }
  hw_mb();
  DCBAAP::Get(cap_length_).FromValue(0).set_PTR(dcbaa_buffer_->phys()[0]).WriteTo(&mmio_.value());
  // Initialize command ring
  doorbell_offset_ = DoorbellOffset::Get().ReadFrom(&mmio_.value());
  // Interrupt moderation interval == 30 microseconds (optimal value derived from scheduler trace)
  // TODO: Change this based on P state (performance states) for power management
  for (uint16_t i = 0; i < irq_count_; i++) {
    status = interrupter(i).Init(i, page_size, &mmio_.value(), offset, 1 << hcsparams2.ERST_MAX(),
                                 doorbell_offset_, this, hcc_, dcbaa_);
    if (status != ZX_OK) {
      zxlogf(ERROR, "interrupter(%d).Init(): %s", i, zx_status_get_string(status));
      return ZX_ERR_INTERNAL;
    }
  }
  status =
      command_ring_.Init(page_size, &bti_, &interrupter(0).ring(), is_32bit_, &mmio_.value(), this);
  if (status != ZX_OK) {
    zxlogf(ERROR, "command_ring_.Init(): %s", zx_status_get_string(status));
    return ZX_ERR_INTERNAL;
  }
  CRCR cr = command_ring_.phys(cap_length_);
  cr.WriteTo(&mmio_.value());

  // Initialize all interrupters.
  // TODO: For optimization, we could demand allocate interrupters and not start all interrupters
  // in the beginning.
  for (uint16_t i = 0; i < irq_count_; i++) {
    if (status = interrupter(i).Start(offset, mmio_.value().View(0)); status != ZX_OK) {
      zxlogf(ERROR, "interrupter(%d).Start(): %s", i, zx_status_get_string(status));
      return ZX_ERR_INTERNAL;
    }
  }
  init_txn_->Reply(ZX_OK);  // This will make the device visible and able to be unbound.
  sync_completion_wait(&bus_completion, ZX_TIME_INFINITE);
  USBCMD::Get(cap_length_)
      .ReadFrom(&mmio_.value())
      .set_ENABLE(1)
      .set_INTE(1)
      .set_HSEE(1)
      .set_EWE(1)
      .WriteTo(&mmio_.value());
  while (USBSTS::Get(cap_length_).ReadFrom(&mmio_.value()).HCHalted()) {
    zx::nanosleep(zx::deadline_after(zx::msec(1)));
  }

  sync_completion_signal(&bringup_);
  return ZX_OK;
}

zx_status_t UsbXhci::Init() {
  if (!(pci_.is_valid() || pdev_.is_valid())) {
    return ZX_ERR_IO_INVALID;
  }

  zx::result result = outgoing_.AddService<fuchsia_hardware_usb_hci::UsbHciService>(
      fuchsia_hardware_usb_hci::UsbHciService::InstanceHandler({
          .device = bindings_.CreateHandler(this, dispatcher_, fidl::kIgnoreBindingClosure),
      }));
  if (result.is_error()) {
    zxlogf(ERROR, "Failed to add service %s", result.status_string());
    return result.status_value();
  }
  auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
  if (endpoints.is_error()) {
    return endpoints.status_value();
  }
  result = outgoing_.Serve(std::move(endpoints->server));
  if (result.is_error()) {
    zxlogf(ERROR, "Failed to service the outgoing directory");
    return result.status_value();
  }

  std::array offers = {
      fuchsia_hardware_usb_hci::UsbHciService::Name,
  };
  zx_status_t status = DdkAdd(ddk::DeviceAddArgs("xhci")
                                  .set_inspect_vmo(inspect_.inspector.DuplicateVmo())
                                  .set_fidl_service_offers(offers)
                                  .set_outgoing_dir(endpoints->client.TakeChannel()));
  if (status != ZX_OK) {
    zxlogf(ERROR, "DdkAdd() error: %s", zx_status_get_string(status));
    return status;
  }

  return ZX_OK;
}

void UsbXhci::DdkInit(ddk::InitTxn txn) {
  init_txn_ = std::move(txn);
  thrd_t init_thread;
  if (thrd_create_with_name(
          &init_thread,
          [](void* ctx) {
            UsbXhci* hci = static_cast<UsbXhci*>(ctx);
            return hci->InitThread();
          },
          this, "xhci-init-thread") != thrd_success) {
    return init_txn_->Reply(ZX_ERR_INTERNAL);  // This will schedule unbinding of the device.
  }
  init_thread_ = init_thread;
  // The init thread will reply to |init_txn_| once it is ready to make the device visible
  // and able to be unbound.
}

void UsbXhci::ConnectToEndpoint(ConnectToEndpointRequest& request,
                                ConnectToEndpointCompleter::Sync& completer) {
  auto state = device_state_[request.device_id()];
  if (!state) {
    zxlogf(ERROR, "%s expects that slot is in use. state should not be nullptr", __func__);
    completer.Reply(fit::as_error(ZX_ERR_IO_NOT_PRESENT));
    return;
  }
  uint8_t index = XhciEndpointIndex(request.ep_addr());
  fbl::AutoLock _(&state->transaction_lock());
  if (state->IsDisconnecting()) {
    completer.Reply(fit::as_error(ZX_ERR_IO_NOT_PRESENT));
    return;
  }
  auto& ep = state->GetEndpoint(index - 1);
  ep.Connect(ep.dispatcher(), std::move(request.ep()));
  completer.Reply(fit::ok());
}

TRBPromise UsbXhci::SubmitCommand(const TRB& command, std::unique_ptr<TRBContext> trb_context) {
  fpromise::bridge<TRB*, zx_status_t> bridge;
  trb_context->completer = std::move(bridge.completer);
  zx_status_t status = command_ring_.AddTRB(command, std::move(trb_context));
  if (status != ZX_OK) {
    return fpromise::make_result_promise(
               fpromise::result<TRB*, zx_status_t>(fpromise::error(status)))
        .box();
  }
  // Ring the doorbell
  DOORBELL::Get(doorbell_offset_, 0).FromValue(0).WriteTo(&mmio_.value());
  return bridge.consumer.promise().box();
}

// Initialize xHCI Inspect node and values.
void Inspect::Init(uint16_t hci_version_in, HCSPARAMS1& hcs1, HCCPARAMS1& hcc1) {
  root = inspector.GetRoot().CreateChild("usb-xhci");

  hci_version = root.CreateUint("hci_version", hci_version_in);
  max_device_slots = root.CreateUint("max_device_slots", hcs1.MaxSlots());
  max_interrupters = root.CreateUint("max_interrupters", hcs1.MaxIntrs());
  max_ports = root.CreateUint("max_ports", hcs1.MaxPorts());
  has_64_bit_addressing = root.CreateBool("has_64_bit_addressing", hcc1.AC64());
  context_size_bytes = root.CreateUint("context_size_bytes", hcc1.CSZ() == 1 ? 64 : 32);
}

// Static function; called by the DDK bind operation.
zx_status_t UsbXhci::Create(void* ctx, zx_device_t* parent) {
  fbl::AllocChecker ac;
  auto dev = std::unique_ptr<UsbXhci>(
      new (&ac) UsbXhci(parent, dma_buffer::CreateBufferFactory(),
                        fdf::Dispatcher::GetCurrent()->async_dispatcher()));
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  zx::result pdev_result = ddk::PDevFidl::Create(parent, ddk::PDevFidl::kFragmentName);
  if (pdev_result.is_ok()) {
    dev->pdev_ = std::move(pdev_result.value());
    // We need at least a PDEV, but the PHY is optional
    // for devices not implementing OTG.
    auto phy = usb_phy::UsbPhyClient::Create(parent, "xhci-phy");
    if (phy.is_ok()) {
      dev->phy_.emplace(std::move(phy.value()));
    }
  } else {
    // A device doesn't have to have a PDEV. It might use PCI instead.
    if (pdev_result.error_value() != ZX_ERR_NOT_FOUND) {
      zxlogf(ERROR, "UsbXhci::Init: could not get platform device protocol: %s",
             pdev_result.status_string());
      return ZX_ERR_NOT_SUPPORTED;
    }
  }

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

  // devmgr is now in charge of the device.
  [[maybe_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

ZIRCON_DRIVER(usb_xhci, usb_xhci::driver_ops, "zircon", "0.1");
