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

#pragma once

#include <bits/limits.h>
#include "trb-sizes.h"
#include "xhci-hw.h"
#include <ddk/io-buffer.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/mutex.h>
#include <memory>
#include <zircon/listnode.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
