Changeset 3038d51 in mainline


Ignore:
Timestamp:
2018-02-01T18:57:17Z (6 years ago)
Author:
Salmelu <salmelu@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
290338b
Parents:
3b5a5e3
Message:

xhci: Multi TRB TD for control and stream bulk

Location:
uspace/drv/bus/usb/xhci
Files:
2 edited

Legend:

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

    r3b5a5e3 r3038d51  
    8888        if (dev->speed >= USB_SPEED_SUPER) {
    8989                ep->packets_per_uframe = xhci_ep->max_burst * xhci_ep->mult;
    90                 ep->max_transfer_size = ep->max_packet_size * ep->packets_per_uframe;
     90                if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS
     91                        || ep->transfer_type == USB_TRANSFER_INTERRUPT) {
     92                        ep->max_transfer_size = ep->max_packet_size * ep->packets_per_uframe;
     93                }
     94                else {
     95                        ep->max_transfer_size = 200 * PAGE_SIZE;
     96                }
    9197        }
    9298
  • uspace/drv/bus/usb/xhci/transfers.c

    r3b5a5e3 r3038d51  
    133133
    134134static void trb_set_buffer(xhci_transfer_t *transfer, xhci_trb_t *trb,
    135         size_t i, size_t total)
     135        size_t i, size_t total, size_t *remaining)
    136136{
    137137        const uintptr_t ptr = dma_buffer_phys(&transfer->hc_buffer,
     
    140140        trb->parameter = host2xhci(64, ptr);
    141141        TRB_CTRL_SET_TD_SIZE(*trb, max(31, total - i - 1));
    142         if (i < total - 1) {
     142        if (*remaining > PAGE_SIZE) {
    143143                TRB_CTRL_SET_XFER_LEN(*trb, PAGE_SIZE);
     144                *remaining -= PAGE_SIZE;
    144145        }
    145146        else {
    146                 const size_t size = ((transfer->batch.buffer_size - 1) % PAGE_SIZE) + 1;
    147                 TRB_CTRL_SET_XFER_LEN(*trb, size);
     147                TRB_CTRL_SET_XFER_LEN(*trb, *remaining);
     148                *remaining = 0;
    148149        }
    149150}
     
    156157        usb_device_request_setup_packet_t* setup = &batch->setup.packet;
    157158
    158         xhci_trb_t trbs[3];
    159         int trbs_used = 0;
    160 
    161         xhci_trb_t *trb_setup = trbs + trbs_used++;
     159        size_t buffer_count = 0;
     160        if (setup->length > 0) {
     161                buffer_count = calculate_trb_count(transfer);
     162        }
     163
     164        xhci_trb_t trbs[buffer_count + 2];
     165
     166        xhci_trb_t *trb_setup = trbs;
    162167        xhci_trb_clean(trb_setup);
    163168
     
    178183
    179184        /* Data stage */
    180         xhci_trb_t *trb_data = NULL;
    181185        if (setup->length > 0) {
    182                 trb_data = trbs + trbs_used++;
    183                 xhci_trb_clean(trb_data);
    184 
    185                 trb_data->parameter = host2xhci(64, transfer->hc_buffer.phys);
    186 
    187                 // data size (sent for OUT, or buffer size)
    188                 TRB_CTRL_SET_XFER_LEN(*trb_data, batch->buffer_size);
    189                 // FIXME: TD size 4.11.2.4
    190                 TRB_CTRL_SET_TD_SIZE(*trb_data, 1);
    191 
    192                 // Some more fields here, no idea what they mean
    193                 TRB_CTRL_SET_TRB_TYPE(*trb_data, XHCI_TRB_TYPE_DATA_STAGE);
    194 
    195186                int stage_dir = REQUEST_TYPE_IS_DEVICE_TO_HOST(setup->request_type)
    196187                                        ? STAGE_IN : STAGE_OUT;
    197                 TRB_CTRL_SET_DIR(*trb_data, stage_dir);
     188                size_t remaining = transfer->batch.buffer_size;
     189
     190                for (size_t i = 0; i < buffer_count; ++i) {
     191                        xhci_trb_clean(&trbs[i + 1]);
     192                        trb_set_buffer(transfer, &trbs[i + 1], i, buffer_count, &remaining);
     193
     194                        TRB_CTRL_SET_DIR(trbs[i + 1], stage_dir);
     195                        TRB_CTRL_SET_TRB_TYPE(trbs[i + 1], XHCI_TRB_TYPE_DATA_STAGE);
     196
     197                        if (i == buffer_count - 1) break;
     198
     199                        /* Set the chain bit as this is not the last TRB */
     200                        TRB_CTRL_SET_CHAIN(trbs[i], 1);
     201                }
    198202        }
    199203
    200204        /* Status stage */
    201         xhci_trb_t *trb_status = trbs + trbs_used++;
     205        xhci_trb_t *trb_status = trbs + buffer_count + 1;
    202206        xhci_trb_clean(trb_status);
    203207
     
    215219
    216220        return xhci_trb_ring_enqueue_multiple(get_ring(transfer), trbs,
    217             trbs_used, &transfer->interrupt_trb_phys);
     221            buffer_count + 2, &transfer->interrupt_trb_phys);
    218222}
    219223
     
    224228        if (!ep->primary_stream_data_size) {
    225229                const size_t buffer_count = calculate_trb_count(transfer);
    226                 xhci_trb_ring_t* ring = get_ring(transfer);
    227230                xhci_trb_t trbs[buffer_count];
     231                size_t remaining = transfer->batch.buffer_size;
    228232
    229233                for (size_t i = 0; i < buffer_count; ++i) {
    230234                        xhci_trb_clean(&trbs[i]);
    231                         trb_set_buffer(transfer, &trbs[i], i, buffer_count);
     235                        trb_set_buffer(transfer, &trbs[i], i, buffer_count, &remaining);
    232236                        TRB_CTRL_SET_TRB_TYPE(trbs[i], XHCI_TRB_TYPE_NORMAL);
    233237
     
    239243                /* Set the interrupt bit for last TRB */
    240244                TRB_CTRL_SET_IOC(trbs[buffer_count - 1], 1);
     245
     246                xhci_trb_ring_t* ring = get_ring(transfer);
    241247                return xhci_trb_ring_enqueue_multiple(ring, &trbs[0], buffer_count,
    242248                        &transfer->interrupt_trb_phys);
    243249        }
    244250        else {
    245                 xhci_trb_t trb;
    246                 xhci_trb_clean(&trb);
    247                 trb.parameter = host2xhci(64, transfer->hc_buffer.phys);
    248 
    249                 // data size (sent for OUT, or buffer size)
    250                 TRB_CTRL_SET_XFER_LEN(trb, transfer->batch.buffer_size);
    251                 TRB_CTRL_SET_TD_SIZE(trb, 2);
    252                 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
    253                 TRB_CTRL_SET_CHAIN(trb, 1);
    254                 TRB_CTRL_SET_ENT(trb, 1);
    255 
    256251                xhci_trb_ring_t* ring = get_ring(transfer);
    257252                if (!ring) {
     
    259254                }
    260255
    261                 int err = xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
    262 
    263                 if (err) {
    264                         return err;
    265                 }
    266 
    267                 xhci_trb_clean(&trb);
    268                 trb.parameter = host2xhci(64, (uintptr_t) transfer);
    269                 TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_EVENT_DATA);
    270                 TRB_CTRL_SET_IOC(trb, 1);
    271 
    272                 return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
     256                const size_t buffer_count = calculate_trb_count(transfer);
     257                xhci_trb_t trbs[buffer_count + 1];
     258                size_t remaining = transfer->batch.buffer_size;
     259
     260                for (size_t i = 0; i < buffer_count; ++i) {
     261                        xhci_trb_clean(&trbs[i]);
     262                        trb_set_buffer(transfer, &trbs[i], i, buffer_count + 1, &remaining);
     263                        TRB_CTRL_SET_TRB_TYPE(trbs[i], XHCI_TRB_TYPE_NORMAL);
     264                        TRB_CTRL_SET_CHAIN(trbs[i], 1);
     265                }
     266                TRB_CTRL_SET_ENT(trbs[buffer_count - 1], 1);
     267
     268                xhci_trb_clean(&trbs[buffer_count]);
     269                trbs[buffer_count].parameter = host2xhci(64, (uintptr_t) transfer);
     270                TRB_CTRL_SET_TRB_TYPE(trbs[buffer_count], XHCI_TRB_TYPE_EVENT_DATA);
     271                TRB_CTRL_SET_IOC(trbs[buffer_count], 1);
     272
     273                return xhci_trb_ring_enqueue_multiple(ring, &trbs[0], buffer_count + 1,
     274                        &transfer->interrupt_trb_phys);
    273275        }
    274276}
     
    277279{
    278280        const size_t buffer_count = calculate_trb_count(transfer);
    279         xhci_trb_ring_t* ring = get_ring(transfer);
    280281        xhci_trb_t trbs[buffer_count];
     282        size_t remaining = transfer->batch.buffer_size;
    281283
    282284        for (size_t i = 0; i < buffer_count; ++i) {
    283285                xhci_trb_clean(&trbs[i]);
    284                 trb_set_buffer(transfer, &trbs[i], i, buffer_count);
     286                trb_set_buffer(transfer, &trbs[i], i, buffer_count, &remaining);
    285287                TRB_CTRL_SET_TRB_TYPE(trbs[i], XHCI_TRB_TYPE_NORMAL);
    286288
     
    292294        /* Set the interrupt bit for last TRB */
    293295        TRB_CTRL_SET_IOC(trbs[buffer_count - 1], 1);
     296
     297        xhci_trb_ring_t* ring = get_ring(transfer);
    294298        return xhci_trb_ring_enqueue_multiple(ring, &trbs[0], buffer_count,
    295299                &transfer->interrupt_trb_phys);
Note: See TracChangeset for help on using the changeset viewer.