// 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.

#ifndef SRC_DEVICES_USB_DRIVERS_XHCI_XHCI_TRB_H_
#define SRC_DEVICES_USB_DRIVERS_XHCI_XHCI_TRB_H_

#include <zircon/listnode.h>

#include <cassert>
#include <memory>

#include <bits/limits.h>
#include <ddk/io-buffer.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/mutex.h>

#include "trb-sizes.h"
#include "xhci-hw.h"

namespace usb_xhci {

class IoBufferContainer;
// IO Buffer Container to allow nesting an IoBuffer
// in an intrusive doubly-linked list.
class IoBufferContainer : public fbl::DoublyLinkedListable<std::unique_ptr<IoBufferContainer>> {
 public:
  IoBufferContainer(ddk::IoBuffer buffer) : buffer_(std::move(buffer)) {}
  const ddk::IoBuffer* operator->() const { return &buffer_; }
  const ddk::IoBuffer& operator*() { return buffer_; }

 private:
  ddk::IoBuffer buffer_;
};

// Represents a virtual memory address mapping.
// Contains information about the virtual range,
// and physical starting address for contiguous mappings.
struct VirtualAddress {
  VirtualAddress() {}
  VirtualAddress(zx_vaddr_t virt_start, size_t virt_end)
      : virt_start(virt_start), virt_end(virt_end) {}
  VirtualAddress(size_t virt_start)
      : virt_start(virt_start), virt_end((virt_start + PAGE_SIZE) - 1) {}
  bool operator<(const VirtualAddress& other) const {
    return (virt_start / PAGE_SIZE) < (other.virt_start / PAGE_SIZE);
  }
  bool operator==(const VirtualAddress& other) const {
    return (virt_start / PAGE_SIZE) == (other.virt_start / PAGE_SIZE);
  }
  size_t GetKey() const { return virt_start / PAGE_SIZE; }
  zx_vaddr_t virt_start = 0;
  zx_vaddr_t virt_end = 0;
  size_t phys_start = 0;
};

// Constant-size map implementation with O(n) lookup time,
// and O(1) insertion time. Maintains a mapping of Keys to Values.
template <typename Key, typename Value, size_t Count>
class XhciMap {
 public:
  XhciMap() {}
  // Retrieves a given key, or creates one if it doesn't already exist
  // Asserts if the number of keys exceeds the statically-allocated buffer
  // size.
  Value& operator[](const Key& key) {
    for (size_t i = 0; i < len_; i++) {
      if (data_[i].first == key) {
        return data_[i].second;
      }
    }
    assert(len_ < Count);
    data_[len_].first = key;
    return data_[len_++].second;
  }
  // Retrieves the std::pair<Key, Value> for a given Key.
  // Returns nullptr if the key is not found in the map.
  std::pair<Key, Value>* get(const Key& key) {
    for (size_t i = 0; i < len_; i++) {
      if (data_[i].first == key) {
        return data_ + i;
      }
    }
    return nullptr;
  }
  // Removes all entries from this map
  void clear() {
    for (size_t i = 0; i < len_; i++) {
      data_[i] = {};
    }
    len_ = 0;
  }

 private:
  size_t len_ = 0;
  std::pair<Key, Value> data_[Count];
};

// used for both command ring and transfer rings
struct xhci_transfer_ring_t {
  fbl::DoublyLinkedList<std::unique_ptr<IoBufferContainer>> buffers;
  XhciMap<VirtualAddress, uint64_t, TRANSFER_RING_SIZE / sizeof(xhci_trb_t)> virt_to_phys_map;
  // Map of physical page indices to virtual addresses
  XhciMap<zx_paddr_t, zx_vaddr_t, TRANSFER_RING_SIZE / sizeof(xhci_trb_t)> phys_to_virt_map;
  xhci_trb_t* start;
  xhci_trb_t* current_trb;  // next to be filled by producer
  uint8_t pcs;              // producer cycle status
  xhci_trb_t* dequeue_ptr;  // next to be processed by consumer
                            // (not used for command ring)
  size_t size;              // number of TRBs in ring
  bool full;                // true if there are no available TRBs,
                            // this is needed to differentiate between
                            // an empty and full ring state
  fbl::Mutex xfer_lock;
};

struct EventMapping {
  uint64_t phys = 0;
  xhci_trb_t* next = nullptr;
  EventMapping() {}
  EventMapping(uint64_t phys) : phys(phys) {}
};

struct xhci_event_ring_t {
  fbl::DoublyLinkedList<std::unique_ptr<IoBufferContainer>> buffers;
  XhciMap<VirtualAddress, EventMapping, TRANSFER_RING_SIZE / sizeof(xhci_trb_t)> virt_to_phys_map;
  XhciMap<zx_paddr_t, zx_vaddr_t, TRANSFER_RING_SIZE / sizeof(xhci_trb_t)> phys_to_virt_map;
  xhci_trb_t* start;
  xhci_trb_t* current;
  xhci_trb_t* end;
  uint8_t ccs;  // consumer cycle status
  fbl::Mutex xfer_lock;
};

zx_status_t xhci_transfer_ring_init(xhci_transfer_ring_t* tr, zx_handle_t bti_handle, int count);
void xhci_transfer_ring_free(xhci_transfer_ring_t* ring);
size_t xhci_transfer_ring_free_trbs(xhci_transfer_ring_t* ring);
zx_status_t xhci_event_ring_init(xhci_event_ring_t*, zx_handle_t bti_handle,
                                 erst_entry_t* erst_array, int count);
void xhci_event_ring_free(xhci_event_ring_t* ring);
void xhci_clear_trb(xhci_trb_t* trb);
// Converts a transfer trb into a NO-OP transfer TRB, does nothing if it is the LINK TRB.
void xhci_set_transfer_noop_trb(xhci_trb_t* trb);
xhci_trb_t* xhci_read_trb_ptr(xhci_transfer_ring_t* ring, xhci_trb_t* trb);
xhci_trb_t* xhci_next_evt(xhci_event_ring_t* ring, xhci_trb_t* trb);
xhci_trb_t* xhci_get_next_trb(xhci_transfer_ring_t* ring, xhci_trb_t* trb);
void xhci_increment_ring(xhci_transfer_ring_t* ring);
void xhci_set_dequeue_ptr(xhci_transfer_ring_t* ring, xhci_trb_t* new_ptr);

// Returns the TRB corresponding to the given physical address, or nullptr if the address is
// invalid.
xhci_trb_t* xhci_transfer_ring_phys_to_trb(xhci_transfer_ring_t* ring, zx_paddr_t phys);

static inline zx_paddr_t xhci_transfer_ring_current_phys(xhci_transfer_ring_t* ring) {
  auto physmap =
      ring->virt_to_phys_map.get(VirtualAddress(reinterpret_cast<size_t>(ring->current_trb)));
  if (physmap == nullptr) {
    abort();
  }
  return physmap->second +
         (reinterpret_cast<size_t>(ring->current_trb) - physmap->first.virt_start);
}

static inline zx_paddr_t xhci_event_ring_current_phys(xhci_event_ring_t* ring) {
  auto physmap =
      ring->virt_to_phys_map.get(VirtualAddress(reinterpret_cast<size_t>(ring->current)));
  if (physmap == nullptr) {
    abort();
  }
  return physmap->second.phys +
         (reinterpret_cast<size_t>(ring->current) - physmap->first.virt_start);
}
struct xhci_t;
// Enlarges the XHCI rings. The caller must ensure exclusive ownership of the rings
// before invoking this function. Refer to XHCI 4.9.2.3
zx_status_t xhci_enlarge_ring(xhci_t* xhci, xhci_transfer_ring_t* transfer);

}  // namespace usb_xhci

#endif  // SRC_DEVICES_USB_DRIVERS_XHCI_XHCI_TRB_H_
