1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <ddk/debug.h>
6#include <string.h>
7
8#include "xhci-transfer-common.h"
9
10void xhci_print_trb(xhci_transfer_ring_t* ring, xhci_trb_t* trb) {
11    int index = trb - ring->start;
12    uint32_t* ptr = (uint32_t *)trb;
13    uint64_t paddr = io_buffer_phys(&ring->buffer) + index * sizeof(xhci_trb_t);
14
15    zxlogf(LSPEW, "trb[%03d] %p: %08X %08X %08X %08X\n", index, (void *)paddr, ptr[0], ptr[1], ptr[2], ptr[3]);
16}
17
18void xhci_transfer_state_init(xhci_transfer_state_t* state, usb_request_t* req,
19                              uint8_t ep_type, uint16_t ep_max_packet_size) {
20    memset(state, 0, sizeof(*state));
21
22    // compute number of packets needed for this transaction
23    if (req->header.length > 0) {
24        usb_request_phys_iter_init(&state->phys_iter, req, XHCI_MAX_DATA_BUFFER);
25        zx_paddr_t dummy_paddr;
26        while (usb_request_phys_iter_next(&state->phys_iter, &dummy_paddr) > 0) {
27            state->packet_count++;
28        }
29    }
30
31    usb_request_phys_iter_init(&state->phys_iter, req, XHCI_MAX_DATA_BUFFER);
32
33    usb_setup_t* setup = (req->header.ep_address == 0 ? &req->setup : NULL);
34    if (setup) {
35        state->direction = setup->bmRequestType & USB_ENDPOINT_DIR_MASK;
36        state->needs_status = true;
37    } else {
38        state->direction = req->header.ep_address & USB_ENDPOINT_DIR_MASK;
39    }
40    state->needs_data_event = true;
41    // Zero length bulk transfers are allowed. We should have at least one transfer TRB
42    // to avoid consecutive event data TRBs on a transfer ring.
43    // See XHCI spec, section 4.11.5.2
44    state->needs_transfer_trb = ep_type == USB_ENDPOINT_BULK;
45
46    // send zero length packet if send_zlp is set and transfer is a multiple of max packet size
47    state->needs_zlp = req->header.send_zlp && (req->header.length % ep_max_packet_size) == 0;
48}
49
50zx_status_t xhci_queue_data_trbs(xhci_transfer_ring_t* ring, xhci_transfer_state_t* state,
51                                 usb_request_t* req, int interrupter_target, bool isochronous) {
52    usb_header_t* header = &req->header;
53    uint64_t frame = header->frame;
54    size_t free_trbs = xhci_transfer_ring_free_trbs(ring);
55
56    zx_paddr_t paddr;
57    size_t transfer_size = 0;
58    bool first_packet = (state->phys_iter.offset == 0);
59    while (free_trbs > 0 && (((transfer_size = usb_request_phys_iter_next(&state->phys_iter, &paddr)) > 0) ||
60                             state->needs_transfer_trb || state->needs_zlp)) {
61        xhci_trb_t* trb = ring->current;
62        xhci_clear_trb(trb);
63        XHCI_WRITE64(&trb->ptr, paddr);
64        XHCI_SET_BITS32(&trb->status, XFER_TRB_XFER_LENGTH_START, XFER_TRB_XFER_LENGTH_BITS,
65                        transfer_size);
66        // number of packets remaining after this one
67        uint32_t td_size = --state->packet_count;
68        if (state->needs_zlp) {
69            td_size++;
70        }
71        XHCI_SET_BITS32(&trb->status, XFER_TRB_TD_SIZE_START, XFER_TRB_TD_SIZE_BITS, td_size);
72        XHCI_SET_BITS32(&trb->status, XFER_TRB_INTR_TARGET_START, XFER_TRB_INTR_TARGET_BITS,
73                        interrupter_target);
74        uint32_t control_bits = TRB_CHAIN;
75        if (td_size == 0) {
76            control_bits |= XFER_TRB_ENT;
77        }
78        if (header->ep_address == 0 && first_packet) {
79            // use TRB_TRANSFER_DATA for first data packet on setup requests
80            control_bits |= (state->direction == USB_DIR_IN ? XFER_TRB_DIR_IN : XFER_TRB_DIR_OUT);
81            trb_set_control(trb, TRB_TRANSFER_DATA, control_bits);
82        } else if (isochronous && first_packet) {
83            // use TRB_TRANSFER_ISOCH for first data packet on isochronous endpoints
84            if (frame == 0) {
85                // set SIA bit to schedule packet ASAP
86                control_bits |= XFER_TRB_SIA;
87            } else {
88                // schedule packet for specified frame
89                control_bits |= (((frame % 2048) << XFER_TRB_FRAME_ID_START) &
90                                 XHCI_MASK(XFER_TRB_FRAME_ID_START, XFER_TRB_FRAME_ID_BITS));
91           }
92            trb_set_control(trb, TRB_TRANSFER_ISOCH, control_bits);
93        } else {
94            trb_set_control(trb, TRB_TRANSFER_NORMAL, control_bits);
95        }
96        if (driver_get_log_flags() & DDK_LOG_SPEW) xhci_print_trb(ring, trb);
97        xhci_increment_ring(ring);
98        free_trbs--;
99
100        first_packet = false;
101        state->needs_transfer_trb = false;
102        if (transfer_size == 0) {
103            // ZLP (if there was one) has been sent
104            state->needs_zlp = false;
105        }
106    }
107
108    if (state->phys_iter.offset < header->length) {
109        // still more data to queue, but we are out of TRBs.
110        // come back and finish later.
111        return ZX_ERR_SHOULD_WAIT;
112    }
113
114    if (state->needs_data_event) {
115        if (free_trbs == 0) {
116            // will need to do this later
117            return ZX_ERR_SHOULD_WAIT;
118        }
119
120        // Queue event data TRB
121        xhci_trb_t* trb = ring->current;
122        xhci_clear_trb(trb);
123        trb_set_ptr(trb, req);
124        XHCI_SET_BITS32(&trb->status, XFER_TRB_INTR_TARGET_START, XFER_TRB_INTR_TARGET_BITS,
125                        interrupter_target);
126        trb_set_control(trb, TRB_TRANSFER_EVENT_DATA, XFER_TRB_IOC);
127        if (driver_get_log_flags() & DDK_LOG_SPEW) xhci_print_trb(ring, trb);
128        xhci_increment_ring(ring);
129        free_trbs--;
130        state->needs_data_event = false;
131    }
132    return ZX_OK;
133}
134