Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 17c5e62 in mainline


Ignore:
Timestamp:
2018-01-08T22:30:12Z (4 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master
Children:
0eadfd1e
Parents:
bdd8842c
Message:

xhci: make isoch part of endpoint optional

Location:
uspace
Files:
5 edited

Legend:

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

    rbdd8842c r17c5e62  
    3636#include <usb/host/endpoint.h>
    3737#include <usb/host/hcd.h>
     38#include <usb/descriptor.h>
    3839#include <usb/debug.h>
    3940
     
    368369static endpoint_t *endpoint_create(device_t *dev, const usb_endpoint_descriptors_t *desc)
    369370{
    370         xhci_endpoint_t *ep = calloc(1, sizeof(xhci_endpoint_t));
     371        const usb_transfer_type_t type = USB_ED_GET_TRANSFER_TYPE(desc->endpoint);
     372
     373        xhci_endpoint_t *ep = calloc(1, sizeof(xhci_endpoint_t)
     374                + (type == USB_TRANSFER_ISOCHRONOUS) * sizeof(*ep->isoch));
    371375        if (!ep)
    372376                return NULL;
  • uspace/drv/bus/usb/xhci/endpoint.c

    rbdd8842c r17c5e62  
    8989
    9090        if (xhci_ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) {
    91                 xhci_ep->isoch_max_size = desc->companion.bytes_per_interval
     91                xhci_ep->isoch->max_size = desc->companion.bytes_per_interval
    9292                        ? desc->companion.bytes_per_interval
    9393                        : ep->max_transfer_size;
     
    9595
    9696                /* Allocate and setup isochronous-specific structures. */
    97                 xhci_ep->isoch_enqueue = 0;
    98                 xhci_ep->isoch_dequeue = 0;
    99                 xhci_ep->isoch_started = false;
    100 
    101                 fibril_mutex_initialize(&xhci_ep->isoch_guard);
    102                 fibril_condvar_initialize(&xhci_ep->isoch_avail);
     97                xhci_ep->isoch->enqueue = 0;
     98                xhci_ep->isoch->dequeue = 0;
     99                xhci_ep->isoch->started = false;
     100
     101                fibril_mutex_initialize(&xhci_ep->isoch->guard);
     102                fibril_condvar_initialize(&xhci_ep->isoch->avail);
    103103        }
    104104
     
    266266        int err = EOK;
    267267        while (i < XHCI_ISOCH_BUFFER_COUNT) {
    268                 xhci_isoch_transfer_t *transfer = &xhci_ep->isoch_transfers[i];
    269                 if (dma_buffer_alloc(&transfer->data, xhci_ep->isoch_max_size)) {
     268                xhci_isoch_transfer_t *transfer = &xhci_ep->isoch->transfers[i];
     269                if (dma_buffer_alloc(&transfer->data, xhci_ep->isoch->max_size)) {
    270270                        err = ENOMEM;
    271271                        break;
     
    278278                --i;
    279279                while(i >= 0) {
    280                         dma_buffer_free(&xhci_ep->isoch_transfers[i].data);
     280                        dma_buffer_free(&xhci_ep->isoch->transfers[i].data);
    281281                        --i;
    282282                }
     
    342342        if (xhci_ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) {
    343343                for (size_t i = 0; i < XHCI_ISOCH_BUFFER_COUNT; ++i) {
    344                         dma_buffer_free(&xhci_ep->isoch_transfers[i].data);
     344                        dma_buffer_free(&xhci_ep->isoch->transfers[i].data);
    345345                }
    346346        }
     
    417417        XHCI_EP_INTERVAL_SET(*ctx, fnzb32(ep->interval) % 32 - 1);
    418418
    419         XHCI_EP_MAX_ESIT_PAYLOAD_LO_SET(*ctx, ep->isoch_max_size & 0xFFFF);
    420         XHCI_EP_MAX_ESIT_PAYLOAD_HI_SET(*ctx, (ep->isoch_max_size >> 16) & 0xFF);
     419        XHCI_EP_MAX_ESIT_PAYLOAD_LO_SET(*ctx, ep->isoch->max_size & 0xFFFF);
     420        XHCI_EP_MAX_ESIT_PAYLOAD_HI_SET(*ctx, (ep->isoch->max_size >> 16) & 0xFF);
    421421}
    422422
  • uspace/drv/bus/usb/xhci/endpoint.h

    rbdd8842c r17c5e62  
    9393        uint32_t interval;
    9494
    95         /** The maximum size of an isochronous transfer and therefore the size of buffers */
    96         size_t isoch_max_size;
     95        /** This field is a valid pointer for (and only for) isochronous transfers. */
     96        struct {
     97                /** The maximum size of an isochronous transfer and therefore the size of buffers */
     98                size_t max_size;
    9799
    98         /** Isochronous scheduled transfers with respective buffers */
    99         #define XHCI_ISOCH_BUFFER_COUNT 4
    100         xhci_isoch_transfer_t isoch_transfers[XHCI_ISOCH_BUFFER_COUNT];
     100                /** Isochronous scheduled transfers with respective buffers */
     101                #define XHCI_ISOCH_BUFFER_COUNT 4
     102                xhci_isoch_transfer_t transfers[XHCI_ISOCH_BUFFER_COUNT];
    101103
    102         /** Indices to transfers */
    103         size_t isoch_dequeue, isoch_enqueue;
     104                /** Indices to transfers */
     105                size_t dequeue, enqueue;
    104106
    105         /** Are isochronous transfers started? */
    106         bool isoch_started;
     107                /** Are isochronous transfers started? */
     108                bool started;
    107109
    108         /** Protects common buffers. */
    109         fibril_mutex_t isoch_guard;
     110                /** Protects common buffers. */
     111                fibril_mutex_t guard;
    110112
    111         /** Signals filled buffer. */
    112         fibril_condvar_t isoch_avail;
    113 
     113                /** Signals filled buffer. */
     114                fibril_condvar_t avail;
     115        } isoch [0];
    114116} xhci_endpoint_t;
    115117
  • uspace/drv/bus/usb/xhci/transfers.c

    rbdd8842c r17c5e62  
    237237
    238238static xhci_isoch_transfer_t* isoch_transfer_get_enqueue(xhci_endpoint_t *ep) {
    239         if (((ep->isoch_enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == ep->isoch_dequeue) {
     239        if (((ep->isoch->enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == ep->isoch->dequeue) {
    240240                /* None ready */
    241241                return NULL;
    242242        }
    243         xhci_isoch_transfer_t *isoch_transfer = &ep->isoch_transfers[ep->isoch_enqueue];
    244         ep->isoch_enqueue = (ep->isoch_enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT;
     243        xhci_isoch_transfer_t *isoch_transfer = &ep->isoch->transfers[ep->isoch->enqueue];
     244        ep->isoch->enqueue = (ep->isoch->enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT;
    245245        return isoch_transfer;
    246246}
    247247
    248248static xhci_isoch_transfer_t* isoch_transfer_get_dequeue(xhci_endpoint_t *ep) {
    249         xhci_isoch_transfer_t *isoch_transfer = &ep->isoch_transfers[ep->isoch_dequeue];
    250         ep->isoch_dequeue = (ep->isoch_dequeue + 1) % XHCI_ISOCH_BUFFER_COUNT;
     249        xhci_isoch_transfer_t *isoch_transfer = &ep->isoch->transfers[ep->isoch->dequeue];
     250        ep->isoch->dequeue = (ep->isoch->dequeue + 1) % XHCI_ISOCH_BUFFER_COUNT;
    251251        return isoch_transfer;
    252252}
     
    283283        xhci_trb_clean(&trb);
    284284
    285         fibril_mutex_lock(&xhci_ep->isoch_guard);
     285        fibril_mutex_lock(&xhci_ep->isoch->guard);
    286286        xhci_isoch_transfer_t *isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
    287287        while (!isoch_transfer) {
    288                 fibril_condvar_wait(&xhci_ep->isoch_avail, &xhci_ep->isoch_guard);
     288                fibril_condvar_wait(&xhci_ep->isoch->avail, &xhci_ep->isoch->guard);
    289289                isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
    290290        }
     
    301301                &isoch_transfer->interrupt_trb_phys);
    302302        if (err) {
    303                 fibril_mutex_unlock(&xhci_ep->isoch_guard);
     303                fibril_mutex_unlock(&xhci_ep->isoch->guard);
    304304                return err;
    305305        }
     
    307307        /* If not yet started, start the isochronous endpoint transfers - after buffer count - 1 writes */
    308308        /* The -1 is there because of the enqueue != dequeue check. The buffer must have at least 2 transfers. */
    309         if (((xhci_ep->isoch_enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == xhci_ep->isoch_dequeue && !xhci_ep->isoch_started) {
     309        if (((xhci_ep->isoch->enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == xhci_ep->isoch->dequeue && !xhci_ep->isoch->started) {
    310310                const uint8_t slot_id = xhci_dev->slot_id;
    311311                const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */
    312312                err = hc_ring_doorbell(hc, slot_id, target);
    313                 xhci_ep->isoch_started = true;
    314         }
    315         fibril_mutex_unlock(&xhci_ep->isoch_guard);
     313                xhci_ep->isoch->started = true;
     314        }
     315        fibril_mutex_unlock(&xhci_ep->isoch->guard);
    316316        if (err) {
    317317                return err;
     
    331331                xhci_trb_clean(&trb);
    332332                trb.parameter = isoch_transfer->data.phys;
    333                 isoch_transfer->size = xhci_ep->isoch_max_size;
     333                isoch_transfer->size = xhci_ep->isoch->max_size;
    334334
    335335                int err = schedule_isochronous_trb(ring, xhci_ep, &trb, isoch_transfer->size,
     
    344344        xhci_device_t *xhci_dev)
    345345{
    346         fibril_mutex_lock(&xhci_ep->isoch_guard);
     346        fibril_mutex_lock(&xhci_ep->isoch->guard);
    347347        /* If not yet started, start the isochronous endpoint transfers - before first read */
    348         if (!xhci_ep->isoch_started) {
     348        if (!xhci_ep->isoch->started) {
    349349                xhci_trb_ring_t *ring = get_ring(hc, transfer);
    350350                /* Fill the TRB ring. */
    351351                int err = schedule_isochronous_in_trbs(xhci_ep, ring);
    352352                if (err) {
    353                         fibril_mutex_unlock(&xhci_ep->isoch_guard);
     353                        fibril_mutex_unlock(&xhci_ep->isoch->guard);
    354354                        return err;
    355355                }
     
    359359                err = hc_ring_doorbell(hc, slot_id, target);
    360360                if (err) {
    361                         fibril_mutex_unlock(&xhci_ep->isoch_guard);
     361                        fibril_mutex_unlock(&xhci_ep->isoch->guard);
    362362                        return err;
    363363                }
    364                 xhci_ep->isoch_started = true;
     364                xhci_ep->isoch->started = true;
    365365        }
    366366
    367367        xhci_isoch_transfer_t *isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
    368368        while(!isoch_transfer) {
    369                 fibril_condvar_wait(&xhci_ep->isoch_avail, &xhci_ep->isoch_guard);
     369                fibril_condvar_wait(&xhci_ep->isoch->avail, &xhci_ep->isoch->guard);
    370370                isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
    371371        }
     
    391391
    392392        trb.parameter = isoch_transfer->data.phys;
    393         isoch_transfer->size = xhci_ep->isoch_max_size;
     393        isoch_transfer->size = xhci_ep->isoch->max_size;
    394394
    395395        xhci_trb_ring_t *ring = get_ring(hc, transfer);
    396396        int err = schedule_isochronous_trb(ring, xhci_ep, &trb, isoch_transfer->size,
    397397                &isoch_transfer->interrupt_trb_phys);
    398         fibril_mutex_unlock(&xhci_ep->isoch_guard);
     398        fibril_mutex_unlock(&xhci_ep->isoch->guard);
    399399
    400400        if (err) {
     
    411411        xhci_device_t *xhci_dev)
    412412{
    413         if (transfer->batch.buffer_size > xhci_ep->isoch_max_size) {
     413        if (transfer->batch.buffer_size > xhci_ep->isoch->max_size) {
    414414                usb_log_error("Cannot schedule an oversized isochronous transfer.");
    415415                return EINVAL;
     
    425425
    426426static int handle_isochronous_transfer_event(xhci_hc_t *hc, xhci_trb_t *trb, xhci_endpoint_t *ep) {
    427         fibril_mutex_lock(&ep->isoch_guard);
     427        fibril_mutex_lock(&ep->isoch->guard);
    428428
    429429        int err = EOK;
     
    434434                case XHCI_TRBC_RING_UNDERRUN:
    435435                        /* Rings are unscheduled by xHC now */
    436                         ep->isoch_started = false;
     436                        ep->isoch->started = false;
    437437                        /* For OUT, there was nothing to process */
    438438                        /* For IN, the buffer has overfilled, we empty the buffers and readd TRBs */
    439                         ep->isoch_enqueue = ep->isoch_dequeue = 0;
     439                        ep->isoch->enqueue = ep->isoch->dequeue = 0;
    440440                        err = EIO;
    441441                        break;
     
    462462        }
    463463
    464         fibril_condvar_signal(&ep->isoch_avail);
    465         fibril_mutex_unlock(&ep->isoch_guard);
     464        fibril_condvar_signal(&ep->isoch->avail);
     465        fibril_mutex_unlock(&ep->isoch->guard);
    466466        return err;
    467467}
  • uspace/lib/usb/include/usb/descriptor.h

    rbdd8842c r17c5e62  
    217217#define USB_ED_GET_ADD_OPPS(ed) \
    218218        ((uint16_usb2host((ed).max_packet_size) >> 11) & 0x3)
    219         /** Polling interval in milliseconds.
    220          * Ignored for bulk and control endpoints.
    221          * Isochronous endpoints must use value 1.
    222          * Interrupt endpoints any value from 1 to 255.
     219        /** Polling interval. Different semantics for various (speed, type)
     220         * pairs.
    223221         */
    224222        uint8_t poll_interval;
Note: See TracChangeset for help on using the changeset viewer.