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

Changeset 5c75456 in mainline


Ignore:
Timestamp:
2017-12-29T17:11:14Z (4 years ago)
Author:
Salmelu <salmelu@…>
Branches:
lfn, master
Children:
bf7b747
Parents:
5dfb70c9
git-author:
Salmelu <salmelu@…> (2017-12-29 17:10:05)
git-committer:
Salmelu <salmelu@…> (2017-12-29 17:11:14)
Message:

xhci: isochronous transfers made working

Location:
uspace
Files:
5 edited

Legend:

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

    r5dfb70c9 r5c75456  
    6464        xhci_ep->mult = desc->usb3.mult;
    6565
     66        // TODO: process according to 6.2.3.6 of XHCI specification; hardcoded for HS/SS EPs
     67        xhci_ep->interval = desc->interval - 1;
     68
    6669        if (xhci_ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) {
    6770                xhci_ep->isoch_max_size = desc->usb3.bytes_per_interval
     
    7275                /* Allocate and setup isochronous-specific structures. */
    7376                xhci_ep->isoch_enqueue = 0;
    74                 xhci_ep->isoch_dequeue = XHCI_ISOCH_BUFFER_COUNT - 1;
     77                xhci_ep->isoch_dequeue = 0;
    7578                xhci_ep->isoch_started = false;
    7679
     
    402405        XHCI_EP_TR_DPTR_SET(*ctx, ep->ring.dequeue);
    403406        XHCI_EP_DCS_SET(*ctx, 1);
     407        XHCI_EP_INTERVAL_SET(*ctx, ep->interval);
    404408
    405409        XHCI_EP_MAX_ESIT_PAYLOAD_LO_SET(*ctx, ep->isoch_max_size & 0xFFFF);
     
    420424        XHCI_EP_TR_DPTR_SET(*ctx, ep->ring.dequeue);
    421425        XHCI_EP_DCS_SET(*ctx, 1);
     426
     427        XHCI_EP_INTERVAL_SET(*ctx, ep->interval);
    422428        // TODO: max ESIT payload
    423429}
  • uspace/drv/bus/usb/xhci/endpoint.h

    r5dfb70c9 r5c75456  
    8989        /** Maximum number of bursts within an interval that this endpoint supports */
    9090        uint8_t mult;
     91
     92        /** Scheduling interval for periodic endpoints */
     93        size_t interval;
    9194
    9295        /** The maximum size of an isochronous transfer and therefore the size of buffers */
  • uspace/drv/bus/usb/xhci/transfers.c

    r5dfb70c9 r5c75456  
    234234
    235235static xhci_isoch_transfer_t* isoch_transfer_get_enqueue(xhci_endpoint_t *ep) {
    236         if ((ep->isoch_enqueue % XHCI_ISOCH_BUFFER_COUNT) == ep->isoch_dequeue) {
     236        if (((ep->isoch_enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == ep->isoch_dequeue) {
    237237                /* None ready */
    238238                return NULL;
     
    303303
    304304        /* If not yet started, start the isochronous endpoint transfers - after buffer count - 1 writes */
    305         /* The -2 is there because of the enqueue != dequeue check. The buffer must have at least 2 transfers. */
    306         if (xhci_ep->isoch_enqueue == XHCI_ISOCH_BUFFER_COUNT - 2 && !xhci_ep->isoch_started) {
     305        /* The -1 is there because of the enqueue != dequeue check. The buffer must have at least 2 transfers. */
     306        if (((xhci_ep->isoch_enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == xhci_ep->isoch_dequeue && !xhci_ep->isoch_started) {
    307307                const uint8_t slot_id = xhci_dev->slot_id;
    308308                const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */
     
    322322}
    323323
     324static int schedule_isochronous_in_trbs(xhci_endpoint_t *xhci_ep, xhci_trb_ring_t *ring) {
     325        xhci_trb_t trb;
     326        xhci_isoch_transfer_t *isoch_transfer;
     327        while ((isoch_transfer = isoch_transfer_get_enqueue(xhci_ep)) != NULL) {
     328                xhci_trb_clean(&trb);
     329                trb.parameter = isoch_transfer->data.phys;
     330                isoch_transfer->size = xhci_ep->isoch_max_size;
     331
     332                int err = schedule_isochronous_trb(ring, xhci_ep, &trb, isoch_transfer->size,
     333                        &isoch_transfer->interrupt_trb_phys);
     334                if (err)
     335                        return err;
     336        }
     337        return EOK;
     338}
     339
    324340static int schedule_isochronous_in(xhci_hc_t* hc, xhci_transfer_t* transfer, xhci_endpoint_t *xhci_ep,
    325341        xhci_device_t *xhci_dev)
     
    328344        /* If not yet started, start the isochronous endpoint transfers - before first read */
    329345        if (!xhci_ep->isoch_started) {
     346                xhci_trb_ring_t *ring = get_ring(hc, transfer);
     347                /* Fill the TRB ring. */
     348                int err = schedule_isochronous_in_trbs(xhci_ep, ring);
     349                if (err) {
     350                        fibril_mutex_unlock(&xhci_ep->isoch_guard);
     351                        return err;
     352                }
     353                /* Ring the doorbell to start it. */
    330354                const uint8_t slot_id = xhci_dev->slot_id;
    331355                const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */
    332                 int err = hc_ring_doorbell(hc, slot_id, target);
     356                err = hc_ring_doorbell(hc, slot_id, target);
    333357                if (err) {
    334358                        fibril_mutex_unlock(&xhci_ep->isoch_guard);
     
    406430                case XHCI_TRBC_RING_OVERRUN:
    407431                case XHCI_TRBC_RING_UNDERRUN:
    408                         // TODO: abort the phone; rings are unscheduled by xHC by now
     432                        /* Rings are unscheduled by xHC now */
    409433                        ep->isoch_started = false;
     434                        /* For OUT, there was nothing to process */
     435                        /* For IN, the buffer has overfilled, we empty the buffers and readd TRBs */
     436                        ep->isoch_enqueue = ep->isoch_dequeue = 0;
    410437                        err = EIO;
    411438                        break;
  • uspace/lib/drv/include/usb_iface.h

    r5dfb70c9 r5c75456  
    115115        size_t max_packet_size;
    116116
     117        /** Scheduling interval for HC. Only valid for interrupt/isoch transfer. */
     118        size_t interval;
     119
    117120        /** Number of packets per frame/uframe.
    118121         * Only valid for HS INT and ISO transfers. All others should set to 1*/
  • uspace/lib/usbdev/src/pipes.c

    r5dfb70c9 r5c75456  
    299299        pipe->bus_session = bus_session;
    300300
     301        // TODO: hardcoded, remake to receive from device descriptors
     302        pipe->desc.interval = 14;
     303
    301304        if (transfer_type == USB_TRANSFER_ISOCHRONOUS) {
    302305                ret = usb_isoch_session_initialize(pipe);
Note: See TracChangeset for help on using the changeset viewer.