Changeset 47e9494 in mainline for uspace/drv/bus/usb/xhci/transfers.c


Ignore:
Timestamp:
2018-01-16T18:02:46Z (7 years ago)
Author:
Salmelu <salmelu@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
eeca8a6
Parents:
7d1dd2b
Message:

xhci: stub for streams support

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/xhci/transfers.c

    r7d1dd2b r47e9494  
    3939#include "hc.h"
    4040#include "hw_struct/trb.h"
     41#include "streams.h"
    4142#include "transfers.h"
    4243#include "trb_ring.h"
     
    121122static xhci_trb_ring_t *get_ring(xhci_hc_t *hc, xhci_transfer_t *transfer)
    122123{
    123         return &xhci_endpoint_get(transfer->batch.ep)->ring;
     124        xhci_endpoint_t *ep = xhci_endpoint_get(transfer->batch.ep);
     125        if (ep->primary_stream_data_size == 0) return &ep->ring;
     126        uint32_t stream_id = transfer->batch.target.stream;
     127
     128        xhci_stream_data_t *stream_data = xhci_get_stream_ctx_data(ep, stream_id);
     129        if (stream_data == NULL) {
     130                usb_log_warning("No transfer ring was found for stream %u.", stream_id);
     131                return NULL;
     132        }
     133
     134        return &stream_data->ring;
    124135}
    125136
     
    202213        // data size (sent for OUT, or buffer size)
    203214        TRB_CTRL_SET_XFER_LEN(trb, transfer->batch.buffer_size);
    204         // FIXME: TD size 4.11.2.4
    205         TRB_CTRL_SET_TD_SIZE(trb, 1);
    206 
    207         // we want an interrupt after this td is done
    208         TRB_CTRL_SET_IOC(trb, 1);
    209 
    210         TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
    211 
    212         xhci_trb_ring_t* ring = get_ring(hc, transfer);
    213 
    214         return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
     215
     216        /* The stream-enabled endpoints need to chain ED trb */
     217        xhci_endpoint_t *ep = xhci_endpoint_get(transfer->batch.ep);
     218        if (!ep->primary_stream_data_size) {
     219                // FIXME: TD size 4.11.2.4
     220                TRB_CTRL_SET_TD_SIZE(trb, 1);
     221
     222                // we want an interrupt after this td is done
     223                TRB_CTRL_SET_IOC(trb, 1);
     224                TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
     225
     226                xhci_trb_ring_t* ring = get_ring(hc, transfer);
     227                return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
     228        }
     229        else {
     230                TRB_CTRL_SET_TD_SIZE(trb, 2);
     231                TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
     232                TRB_CTRL_SET_CHAIN(trb, 1);
     233                TRB_CTRL_SET_ENT(trb, 1);
     234
     235                xhci_trb_ring_t* ring = get_ring(hc, transfer);
     236                int err = xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
     237
     238                if (err) {
     239                        return err;
     240                }
     241
     242                xhci_trb_clean(&trb);
     243                trb.parameter = host2xhci(64, (uintptr_t) transfer);
     244                TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_EVENT_DATA);
     245                TRB_CTRL_SET_IOC(trb, 1);
     246
     247                return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
     248        }
    215249}
    216250
     
    267301        xhci_endpoint_t *ep = xhci_endpoint_get(ep_base);
    268302
    269         xhci_trb_ring_update_dequeue(&ep->ring, addr);
    270 
    271         if (ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) {
    272                 isoch_handle_transfer_event(hc, ep, trb);
    273                 endpoint_del_ref(&ep->base);
    274                 return EOK;
    275         }
    276 
    277         fibril_mutex_lock(&ep->base.guard);
    278         usb_transfer_batch_t *batch = ep->base.active_batch;
    279         if (!batch) {
     303        usb_transfer_batch_t *batch;
     304        xhci_transfer_t *transfer;
     305
     306        if (TRB_EVENT_DATA(*trb)) {
     307                assert(ep->base.transfer_type != USB_TRANSFER_ISOCHRONOUS);
     308                /* We are received transfer pointer instead - work with that */
     309                transfer = (xhci_transfer_t *) addr;
     310                xhci_trb_ring_t * ring = get_ring(hc, transfer);
     311                xhci_trb_ring_update_dequeue(ring, transfer->interrupt_trb_phys);
     312                batch = &transfer->batch;
     313
     314                fibril_mutex_lock(&ep->base.guard);
     315                endpoint_deactivate_locked(&ep->base);
    280316                fibril_mutex_unlock(&ep->base.guard);
    281                 endpoint_del_ref(&ep->base);
    282                 return ENOENT;
     317        }
     318        else {
     319                xhci_trb_ring_update_dequeue(&ep->ring, addr);
     320
     321                if (ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) {
     322                        isoch_handle_transfer_event(hc, ep, trb);
     323                        endpoint_del_ref(&ep->base);
     324                        return EOK;
     325                }
     326
     327                fibril_mutex_lock(&ep->base.guard);
     328                batch = ep->base.active_batch;
     329                if (!batch) {
     330                        fibril_mutex_unlock(&ep->base.guard);
     331                        endpoint_del_ref(&ep->base);
     332                        return ENOENT;
     333                }
     334
     335                transfer = xhci_transfer_from_batch(batch);
     336
     337                endpoint_deactivate_locked(&ep->base);
     338                fibril_mutex_unlock(&ep->base.guard);
    283339        }
    284340
     
    296352        }
    297353
    298         endpoint_deactivate_locked(&ep->base);
    299         fibril_mutex_unlock(&ep->base.guard);
    300 
    301         xhci_transfer_t *transfer = xhci_transfer_from_batch(batch);
    302 
    303354        if (batch->dir == USB_DIRECTION_IN) {
    304355                assert(batch->buffer);
     
    370421
    371422        const uint8_t slot_id = xhci_dev->slot_id;
    372         const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */
     423        /* EP Doorbells start at 1 */
     424        const uint8_t target = (xhci_endpoint_index(xhci_ep) + 1) | (batch->target.stream << 16);
    373425        hc_ring_doorbell(hc, slot_id, target);
    374426        return EOK;
Note: See TracChangeset for help on using the changeset viewer.