// Copyright 2018 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 <ddk/debug.h>
#include <usb/usb-request.h>
#include <string.h>

#include "xhci-transfer-common.h"

namespace usb_xhci {

void xhci_print_trb(xhci_transfer_ring_t* ring, xhci_trb_t* trb) {
    size_t index = trb - ring->start;
    uint32_t* ptr = (uint32_t*)trb;
    auto physmap = ring->virt_to_phys_map.get(VirtualAddress(reinterpret_cast<size_t>(trb)));

    uint64_t paddr =
        physmap->second + (reinterpret_cast<size_t>(ring->current_trb) - physmap->first.virt_start);

    zxlogf(LSPEW, "trb[%03zu] %p: %08X %08X %08X %08X\n", index, (void*)paddr, ptr[0], ptr[1],
           ptr[2], ptr[3]);
}

void xhci_transfer_state_init(xhci_transfer_state_t* state, usb_request_t* req,
                              uint8_t ep_type, uint16_t ep_max_packet_size) {
    memset(state, 0, sizeof(*state));

    // compute number of packets needed for this transaction
    if (req->header.length > 0) {
        usb_request_phys_iter_init(&state->phys_iter, req, XHCI_MAX_DATA_BUFFER);
        zx_paddr_t dummy_paddr;
        while (usb_request_phys_iter_next(&state->phys_iter, &dummy_paddr) > 0) {
            state->packet_count++;
        }
    }

    usb_request_phys_iter_init(&state->phys_iter, req, XHCI_MAX_DATA_BUFFER);

    usb_setup_t* setup = (req->header.ep_address == 0 ? &req->setup : nullptr);
    if (setup) {
        state->direction = setup->bmRequestType & USB_ENDPOINT_DIR_MASK;
        state->needs_status = true;
    } else {
        state->direction = req->header.ep_address & USB_ENDPOINT_DIR_MASK;
    }
    state->needs_data_event = true;
    // Zero length bulk transfers are allowed. We should have at least one transfer TRB
    // to avoid consecutive event data TRBs on a transfer ring.
    // See XHCI spec, section 4.11.5.2
    state->needs_transfer_trb = ep_type == USB_ENDPOINT_BULK;

    // send zero length packet if send_zlp is set and transfer is a multiple of max packet size
    state->needs_zlp = req->header.send_zlp && (req->header.length % ep_max_packet_size) == 0;
}

zx_status_t xhci_queue_data_trbs(xhci_transfer_ring_t* ring, xhci_transfer_state_t* state,
                                 usb_request_t* req, int interrupter_target, bool isochronous) {
    usb_header_t* header = &req->header;
    uint64_t frame = header->frame;
    size_t free_trbs = xhci_transfer_ring_free_trbs(ring);

    zx_paddr_t paddr;
    size_t transfer_size = 0;
    bool first_packet = (state->phys_iter.total_iterated == 0);
    while (free_trbs > 0 &&
           (((transfer_size = usb_request_phys_iter_next(&state->phys_iter, &paddr)) > 0) ||
            state->needs_transfer_trb || state->needs_zlp)) {
        xhci_trb_t* trb = ring->current_trb;
        xhci_clear_trb(trb);
        XHCI_WRITE64(&trb->ptr, paddr);
        XHCI_SET_BITS32(&trb->status, XFER_TRB_XFER_LENGTH_START, XFER_TRB_XFER_LENGTH_BITS,
                        static_cast<uint32_t>(transfer_size));
        // number of packets remaining after this one
        uint32_t td_size = --state->packet_count;
        if (state->needs_zlp) {
            td_size++;
        }
        XHCI_SET_BITS32(&trb->status, XFER_TRB_TD_SIZE_START, XFER_TRB_TD_SIZE_BITS, td_size);
        XHCI_SET_BITS32(&trb->status, XFER_TRB_INTR_TARGET_START, XFER_TRB_INTR_TARGET_BITS,
                        interrupter_target);
        uint32_t control_bits = TRB_CHAIN;
        if (td_size == 0) {
            control_bits |= XFER_TRB_ENT;
        }
        if (header->ep_address == 0 && first_packet) {
            // use TRB_TRANSFER_DATA for first data packet on setup requests
            control_bits |= (state->direction == USB_DIR_IN ? XFER_TRB_DIR_IN : XFER_TRB_DIR_OUT);
            trb_set_control(trb, TRB_TRANSFER_DATA, control_bits);
        } else if (isochronous && first_packet) {
            // use TRB_TRANSFER_ISOCH for first data packet on isochronous endpoints
            if (frame == 0) {
                // set SIA bit to schedule packet ASAP
                control_bits |= XFER_TRB_SIA;
            } else {
                // schedule packet for specified frame
                control_bits |= ((static_cast<uint32_t>(frame % 2048) << XFER_TRB_FRAME_ID_START) &
                                 XHCI_MASK(XFER_TRB_FRAME_ID_START, XFER_TRB_FRAME_ID_BITS));
           }
            trb_set_control(trb, TRB_TRANSFER_ISOCH, control_bits);
        } else {
            trb_set_control(trb, TRB_TRANSFER_NORMAL, control_bits);
        }
        if (driver_get_log_flags() & DDK_LOG_SPEW) xhci_print_trb(ring, trb);
        xhci_increment_ring(ring);
        free_trbs--;

        first_packet = false;
        state->needs_transfer_trb = false;
        if (transfer_size == 0) {
            // ZLP (if there was one) has been sent
            state->needs_zlp = false;
        }
    }

    if (state->phys_iter.total_iterated < header->length) {
        // still more data to queue, but we are out of TRBs.
        // come back and finish later.
        return ZX_ERR_SHOULD_WAIT;
    }

    if (state->needs_data_event) {
        if (free_trbs == 0) {
            // will need to do this later
            return ZX_ERR_SHOULD_WAIT;
        }

        // Queue event data TRB
        xhci_trb_t* trb = ring->current_trb;
        xhci_clear_trb(trb);
        trb->ptr = reinterpret_cast<uint64_t>(req);
        XHCI_SET_BITS32(&trb->status, XFER_TRB_INTR_TARGET_START, XFER_TRB_INTR_TARGET_BITS,
                        interrupter_target);
        trb_set_control(trb, TRB_TRANSFER_EVENT_DATA, XFER_TRB_IOC);
        if (driver_get_log_flags() & DDK_LOG_SPEW) xhci_print_trb(ring, trb);
        xhci_increment_ring(ring);
        free_trbs--;
        state->needs_data_event = false;
    }
    return ZX_OK;
}

} // namespace usb_xhci
