Ignore:
File:
1 edited

Legend:

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

    r3038d51 re454d9c  
    126126}
    127127
    128 static int calculate_trb_count(xhci_transfer_t *transfer)
    129 {
    130         const size_t size = transfer->batch.buffer_size;
    131         return (size + PAGE_SIZE - 1 )/ PAGE_SIZE;
    132 }
    133 
    134 static void trb_set_buffer(xhci_transfer_t *transfer, xhci_trb_t *trb,
    135         size_t i, size_t total, size_t *remaining)
    136 {
    137         const uintptr_t ptr = dma_buffer_phys(&transfer->hc_buffer,
    138                 transfer->hc_buffer.virt + i * PAGE_SIZE);
    139 
    140         trb->parameter = host2xhci(64, ptr);
    141         TRB_CTRL_SET_TD_SIZE(*trb, max(31, total - i - 1));
    142         if (*remaining > PAGE_SIZE) {
    143                 TRB_CTRL_SET_XFER_LEN(*trb, PAGE_SIZE);
    144                 *remaining -= PAGE_SIZE;
    145         }
    146         else {
    147                 TRB_CTRL_SET_XFER_LEN(*trb, *remaining);
    148                 *remaining = 0;
    149         }
    150 }
    151 
    152128static int schedule_control(xhci_hc_t* hc, xhci_transfer_t* transfer)
    153129{
     
    157133        usb_device_request_setup_packet_t* setup = &batch->setup.packet;
    158134
    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;
     135        xhci_trb_t trbs[3];
     136        int trbs_used = 0;
     137
     138        xhci_trb_t *trb_setup = trbs + trbs_used++;
    167139        xhci_trb_clean(trb_setup);
    168140
     
    183155
    184156        /* Data stage */
     157        xhci_trb_t *trb_data = NULL;
    185158        if (setup->length > 0) {
     159                trb_data = trbs + trbs_used++;
     160                xhci_trb_clean(trb_data);
     161
     162                trb_data->parameter = host2xhci(64, transfer->hc_buffer.phys);
     163
     164                // data size (sent for OUT, or buffer size)
     165                TRB_CTRL_SET_XFER_LEN(*trb_data, batch->buffer_size);
     166                // FIXME: TD size 4.11.2.4
     167                TRB_CTRL_SET_TD_SIZE(*trb_data, 1);
     168
     169                // Some more fields here, no idea what they mean
     170                TRB_CTRL_SET_TRB_TYPE(*trb_data, XHCI_TRB_TYPE_DATA_STAGE);
     171
    186172                int stage_dir = REQUEST_TYPE_IS_DEVICE_TO_HOST(setup->request_type)
    187173                                        ? STAGE_IN : STAGE_OUT;
    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                 }
     174                TRB_CTRL_SET_DIR(*trb_data, stage_dir);
    202175        }
    203176
    204177        /* Status stage */
    205         xhci_trb_t *trb_status = trbs + buffer_count + 1;
     178        xhci_trb_t *trb_status = trbs + trbs_used++;
    206179        xhci_trb_clean(trb_status);
    207180
     
    219192
    220193        return xhci_trb_ring_enqueue_multiple(get_ring(transfer), trbs,
    221             buffer_count + 2, &transfer->interrupt_trb_phys);
     194            trbs_used, &transfer->interrupt_trb_phys);
    222195}
    223196
    224197static int schedule_bulk(xhci_hc_t* hc, xhci_transfer_t *transfer)
    225198{
     199        xhci_trb_t trb;
     200        xhci_trb_clean(&trb);
     201        trb.parameter = host2xhci(64, transfer->hc_buffer.phys);
     202
     203        // data size (sent for OUT, or buffer size)
     204        TRB_CTRL_SET_XFER_LEN(trb, transfer->batch.buffer_size);
     205
    226206        /* The stream-enabled endpoints need to chain ED trb */
    227207        xhci_endpoint_t *ep = xhci_endpoint_get(transfer->batch.ep);
    228208        if (!ep->primary_stream_data_size) {
    229                 const size_t buffer_count = calculate_trb_count(transfer);
    230                 xhci_trb_t trbs[buffer_count];
    231                 size_t remaining = transfer->batch.buffer_size;
    232 
    233                 for (size_t i = 0; i < buffer_count; ++i) {
    234                         xhci_trb_clean(&trbs[i]);
    235                         trb_set_buffer(transfer, &trbs[i], i, buffer_count, &remaining);
    236                         TRB_CTRL_SET_TRB_TYPE(trbs[i], XHCI_TRB_TYPE_NORMAL);
    237 
    238                         if (i == buffer_count - 1) break;
    239 
    240                         /* Set the chain bit as this is not the last TRB */
    241                         TRB_CTRL_SET_CHAIN(trbs[i], 1);
    242                 }
    243                 /* Set the interrupt bit for last TRB */
    244                 TRB_CTRL_SET_IOC(trbs[buffer_count - 1], 1);
     209                // FIXME: TD size 4.11.2.4
     210                TRB_CTRL_SET_TD_SIZE(trb, 1);
     211
     212                // we want an interrupt after this td is done
     213                TRB_CTRL_SET_IOC(trb, 1);
     214                TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
    245215
    246216                xhci_trb_ring_t* ring = get_ring(transfer);
    247                 return xhci_trb_ring_enqueue_multiple(ring, &trbs[0], buffer_count,
    248                         &transfer->interrupt_trb_phys);
     217                return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
    249218        }
    250219        else {
     220                TRB_CTRL_SET_TD_SIZE(trb, 2);
     221                TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
     222                TRB_CTRL_SET_CHAIN(trb, 1);
     223                TRB_CTRL_SET_ENT(trb, 1);
     224
    251225                xhci_trb_ring_t* ring = get_ring(transfer);
    252226                if (!ring) {
     
    254228                }
    255229
    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);
     230                int err = xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
     231
     232                if (err) {
     233                        return err;
    265234                }
    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);
     235
     236                xhci_trb_clean(&trb);
     237                trb.parameter = host2xhci(64, (uintptr_t) transfer);
     238                TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_EVENT_DATA);
     239                TRB_CTRL_SET_IOC(trb, 1);
     240
     241                return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
    275242        }
    276243}
     
    278245static int schedule_interrupt(xhci_hc_t* hc, xhci_transfer_t* transfer)
    279246{
    280         const size_t buffer_count = calculate_trb_count(transfer);
    281         xhci_trb_t trbs[buffer_count];
    282         size_t remaining = transfer->batch.buffer_size;
    283 
    284         for (size_t i = 0; i < buffer_count; ++i) {
    285                 xhci_trb_clean(&trbs[i]);
    286                 trb_set_buffer(transfer, &trbs[i], i, buffer_count, &remaining);
    287                 TRB_CTRL_SET_TRB_TYPE(trbs[i], XHCI_TRB_TYPE_NORMAL);
    288 
    289                 if (i == buffer_count - 1) break;
    290 
    291                 /* Set the chain bit as this is not the last TRB */
    292                 TRB_CTRL_SET_CHAIN(trbs[i], 1);
    293         }
    294         /* Set the interrupt bit for last TRB */
    295         TRB_CTRL_SET_IOC(trbs[buffer_count - 1], 1);
     247        xhci_trb_t trb;
     248        xhci_trb_clean(&trb);
     249        trb.parameter = host2xhci(64, transfer->hc_buffer.phys);
     250
     251        // data size (sent for OUT, or buffer size)
     252        TRB_CTRL_SET_XFER_LEN(trb, transfer->batch.buffer_size);
     253        // FIXME: TD size 4.11.2.4
     254        TRB_CTRL_SET_TD_SIZE(trb, 1);
     255
     256        // we want an interrupt after this td is done
     257        TRB_CTRL_SET_IOC(trb, 1);
     258
     259        TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
    296260
    297261        xhci_trb_ring_t* ring = get_ring(transfer);
    298         return xhci_trb_ring_enqueue_multiple(ring, &trbs[0], buffer_count,
    299                 &transfer->interrupt_trb_phys);
     262
     263        return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
    300264}
    301265
Note: See TracChangeset for help on using the changeset viewer.