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

Changeset c21e6a5 in mainline


Ignore:
Timestamp:
2018-02-05T00:54:08Z (4 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial
Children:
af16ebe
Parents:
65c059f
git-author:
Ondřej Hlavatý <aearsis@…> (2018-02-05 00:27:40)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-02-05 00:54:08)
Message:

usbhost: prepare buffers for transfers in library

Location:
uspace
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ehci/ehci_batch.c

    r65c059f rc21e6a5  
    6161{
    6262        assert(ehci_batch);
    63         dma_buffer_free(&ehci_batch->dma_buffer);
     63        dma_buffer_free(&ehci_batch->ehci_dma_buffer);
    6464        usb_log_debug2("Batch(%p): disposed", ehci_batch);
    6565        free(ehci_batch);
     
    116116        }
    117117
     118        assert(ehci_batch->td_count > 0);
     119
    118120        const size_t tds_size = ehci_batch->td_count * sizeof(td_t);
    119121
    120         /* Mix setup stage, data and TDs together, we have enough space */
    121         if (size + setup_size + tds_size > 0) {
    122                 if (dma_buffer_alloc(&ehci_batch->dma_buffer, tds_size + setup_size + size)) {
    123                         usb_log_error("Batch %p: Failed to allocate device "
    124                             "buffer", ehci_batch);
    125                         return ENOMEM;
    126                 }
    127                 /* Clean TDs */
    128                 ehci_batch->tds = ehci_batch->dma_buffer.virt;
    129                 memset(ehci_batch->tds, 0, tds_size);
    130                 /* Copy setup data */
    131                 ehci_batch->setup_buffer = ehci_batch->dma_buffer.virt + tds_size;
    132                 memcpy(ehci_batch->setup_buffer, ehci_batch->base.setup.buffer, setup_size);
    133                 /* Copy generic data */
    134                 ehci_batch->data_buffer = ehci_batch->setup_buffer + setup_size;
    135                 if (ehci_batch->base.dir != USB_DIRECTION_IN)
    136                         memcpy(ehci_batch->data_buffer,
    137                             ehci_batch->base.buffer,
    138                             ehci_batch->base.buffer_size);
    139         }
     122        /* Mix setup stage and TDs together, we have enough space */
     123        if (dma_buffer_alloc(&ehci_batch->ehci_dma_buffer, tds_size + setup_size)) {
     124                usb_log_error("Batch %p: Failed to allocate device buffer",
     125                    ehci_batch);
     126                return ENOMEM;
     127        }
     128
     129        /* Clean TDs */
     130        ehci_batch->tds = ehci_batch->ehci_dma_buffer.virt;
     131        memset(ehci_batch->tds, 0, tds_size);
     132
     133        /* Copy setup data */
     134        ehci_batch->setup_buffer = ehci_batch->ehci_dma_buffer.virt + tds_size;
     135        memcpy(ehci_batch->setup_buffer, ehci_batch->base.setup.buffer, setup_size);
     136
     137        /* Generic data already prepared*/
     138        ehci_batch->data_buffer = ehci_batch->base.dma_buffer.virt;
    140139
    141140        if (!batch_setup[ehci_batch->base.ep->transfer_type])
     
    219218        assert(ehci_batch->base.transferred_size <= ehci_batch->base.buffer_size);
    220219
    221         if (ehci_batch->base.dir == USB_DIRECTION_IN)
    222                 memcpy(ehci_batch->base.buffer,
    223                     ehci_batch->data_buffer,
    224                     ehci_batch->base.transferred_size);
    225 
    226220        /* Clear TD pointers */
    227221        ehci_batch->qh->next = LINK_POINTER_TERM;
     
    240234{
    241235        assert(ehci_batch);
    242         qh_set_next_td(ehci_batch->qh, dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[0]));
     236        qh_set_next_td(ehci_batch->qh,
     237            dma_buffer_phys(&ehci_batch->ehci_dma_buffer, &ehci_batch->tds[0]));
    243238}
    244239
     
    275270        /* Setup stage */
    276271        td_init(&ehci_batch->tds[0],
    277             dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[1]),
    278             dma_buffer_phys(&ehci_batch->dma_buffer, ehci_batch->setup_buffer),
     272            dma_buffer_phys(&ehci_batch->ehci_dma_buffer, &ehci_batch->tds[1]),
     273            dma_buffer_phys(&ehci_batch->ehci_dma_buffer, ehci_batch->setup_buffer),
    279274            USB_DIRECTION_BOTH, USB_SETUP_PACKET_SIZE, toggle, false);
    280275        usb_log_debug2("Batch %p: Created CONTROL SETUP TD(%"PRIxn"): "
    281276            "%08x:%08x:%08x", ehci_batch,
    282             dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[0]),
     277            dma_buffer_phys(&ehci_batch->ehci_dma_buffer, &ehci_batch->tds[0]),
    283278            ehci_batch->tds[0].status, ehci_batch->tds[0].next,
    284279            ehci_batch->tds[0].alternate);
     
    287282        unsigned td_current = 1;
    288283        size_t remain_size = ehci_batch->base.buffer_size;
    289         uintptr_t buffer = dma_buffer_phys(&ehci_batch->dma_buffer, ehci_batch->data_buffer);
     284        uintptr_t buffer = dma_buffer_phys(&ehci_batch->base.dma_buffer,
     285            ehci_batch->data_buffer);
    290286        while (remain_size > 0) {
    291287                const size_t transfer_size = min(remain_size, EHCI_TD_MAX_TRANSFER);
     
    293289
    294290                td_init(&ehci_batch->tds[td_current],
    295                     dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[td_current + 1]),
     291                    dma_buffer_phys(&ehci_batch->ehci_dma_buffer, &ehci_batch->tds[td_current + 1]),
    296292                    buffer, data_dir, transfer_size, toggle, false);
    297293                usb_log_debug2("Batch %p: Created CONTROL DATA TD(%"PRIxn"): "
    298294                    "%08x:%08x:%08x", ehci_batch,
    299                     dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[td_current]),
     295                    dma_buffer_phys(&ehci_batch->ehci_dma_buffer, &ehci_batch->tds[td_current]),
    300296                    ehci_batch->tds[td_current].status,
    301297                    ehci_batch->tds[td_current].next,
     
    313309        usb_log_debug2("Batch %p: Created CONTROL STATUS TD %d(%"PRIxn"): "
    314310            "%08x:%08x:%08x", ehci_batch, td_current,
    315             dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[td_current]),
     311            dma_buffer_phys(&ehci_batch->ehci_dma_buffer, &ehci_batch->tds[td_current]),
    316312            ehci_batch->tds[td_current].status,
    317313            ehci_batch->tds[td_current].next,
     
    340336        size_t td_current = 0;
    341337        size_t remain_size = ehci_batch->base.buffer_size;
    342         uintptr_t buffer = dma_buffer_phys(&ehci_batch->dma_buffer, ehci_batch->data_buffer);
     338        uintptr_t buffer = dma_buffer_phys(&ehci_batch->base.dma_buffer,
     339            ehci_batch->data_buffer);
    343340        while (remain_size > 0) {
    344341                const size_t transfer_size = remain_size > EHCI_TD_MAX_TRANSFER
     
    347344                const bool last = (remain_size == transfer_size);
    348345                td_init(&ehci_batch->tds[td_current],
    349                     last ? 0 : dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[td_current + 1]),
     346                    last ? 0 : dma_buffer_phys(&ehci_batch->ehci_dma_buffer,
     347                            &ehci_batch->tds[td_current + 1]),
    350348                    buffer, ehci_batch->base.dir, transfer_size, -1, last);
    351349
    352350                usb_log_debug2("Batch %p: DATA TD(%"PRIxn": %08x:%08x:%08x",
    353351                    ehci_batch,
    354                     dma_buffer_phys(&ehci_batch->dma_buffer, &ehci_batch->tds[td_current]),
     352                    dma_buffer_phys(&ehci_batch->ehci_dma_buffer,
     353                        &ehci_batch->tds[td_current]),
    355354                    ehci_batch->tds[td_current].status,
    356355                    ehci_batch->tds[td_current].next,
  • uspace/drv/bus/usb/ehci/ehci_batch.h

    r65c059f rc21e6a5  
    5151        /** Endpoint descriptor of the target endpoint. */
    5252        qh_t *qh;
    53         /** Data buffer, must be accessible by the EHCI hw. */
    54         dma_buffer_t dma_buffer;
     53        /** Backend for TDs and setup data. */
     54        dma_buffer_t ehci_dma_buffer;
    5555        /** List of TDs needed for the transfer - backed by dma_buffer */
    5656        td_t *tds;
  • uspace/drv/bus/usb/ehci/ehci_rh.c

    r65c059f rc21e6a5  
    147147        batch->error = virthub_base_request(&instance->base, batch->target,
    148148            batch->dir, (void*) batch->setup.buffer,
    149             batch->buffer, batch->buffer_size, &batch->transferred_size);
     149            batch->dma_buffer.virt, batch->buffer_size,
     150            &batch->transferred_size);
    150151        if (batch->error == ENAK) {
    151152                usb_log_debug("RH(%p): BATCH(%p) adding as unfinished",
     
    205206                batch->error = virthub_base_request(&instance->base, batch->target,
    206207                    batch->dir, (void*) batch->setup.buffer,
    207                     batch->buffer, batch->buffer_size, &batch->transferred_size);
     208                    batch->dma_buffer.virt, batch->buffer_size,
     209                    &batch->transferred_size);
    208210                usb_transfer_batch_finish(batch);
    209211        }
  • uspace/drv/bus/usb/ohci/ohci_batch.c

    r65c059f rc21e6a5  
    113113                : 0;
    114114
    115         if (dma_buffer_alloc(&ohci_batch->ohci_dma_buffer, td_size + setup_size + usb_batch->buffer_size)) {
     115        if (dma_buffer_alloc(&ohci_batch->ohci_dma_buffer, td_size + setup_size)) {
    116116                usb_log_error("Failed to allocate OHCI DMA buffer.");
    117117                return ENOMEM;
     
    129129        memcpy(ohci_batch->setup_buffer, usb_batch->setup.buffer, setup_size);
    130130
    131         ohci_batch->data_buffer = ohci_batch->setup_buffer + setup_size;
    132         if (usb_batch->dir == USB_DIRECTION_OUT)
    133                 memcpy(ohci_batch->data_buffer, usb_batch->buffer, usb_batch->buffer_size);
     131        ohci_batch->data_buffer = usb_batch->dma_buffer.virt;
    134132
    135133        batch_setup[usb_batch->ep->transfer_type](ohci_batch);
     
    151149        assert(ohci_batch);
    152150
    153         ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->base.ep);
     151        usb_transfer_batch_t *usb_batch = &ohci_batch->base;
     152        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(usb_batch->ep);
    154153        assert(ohci_ep);
    155154
    156155        usb_log_debug("Batch %p checking %zu td(s) for completion.",
    157             &ohci_batch->base, ohci_batch->td_count);
     156            ohci_batch, ohci_batch->td_count);
    158157        usb_log_debug2("ED: %08x:%08x:%08x:%08x.",
    159158            ohci_ep->ed->status, ohci_ep->ed->td_head,
     
    167166
    168167        /* Assume all data got through */
    169         ohci_batch->base.transferred_size = ohci_batch->base.buffer_size;
     168        usb_batch->transferred_size = usb_batch->buffer_size;
    170169
    171170        /* Check all TDs */
     
    176175                    ohci_batch->tds[i]->next, ohci_batch->tds[i]->be);
    177176
    178                 ohci_batch->base.error = td_error(ohci_batch->tds[i]);
    179                 if (ohci_batch->base.error == EOK) {
     177                usb_batch->error = td_error(ohci_batch->tds[i]);
     178                if (usb_batch->error == EOK) {
    180179                        /* If the TD got all its data through, it will report
    181180                         * 0 bytes remain, the sole exception is INPUT with
     
    190189                         * we leave the very last(unused) TD behind.
    191190                         */
    192                         ohci_batch->base.transferred_size
     191                        usb_batch->transferred_size
    193192                            -= td_remain_size(ohci_batch->tds[i]);
    194193                } else {
    195194                        usb_log_debug("Batch %p found error TD(%zu):%08x.",
    196                             &ohci_batch->base, i, ohci_batch->tds[i]->status);
     195                            ohci_batch, i, ohci_batch->tds[i]->status);
    197196
    198197                        /* ED should be stopped because of errors */
     
    213212                }
    214213        }
    215         assert(ohci_batch->base.transferred_size <=
    216             ohci_batch->base.buffer_size);
    217 
    218         if (ohci_batch->base.dir == USB_DIRECTION_IN)
    219                 memcpy(ohci_batch->base.buffer,
    220                     ohci_batch->data_buffer,
    221                     ohci_batch->base.transferred_size);
     214        assert(usb_batch->transferred_size <= usb_batch->buffer_size);
    222215
    223216        /* Make sure that we are leaving the right TD behind */
  • uspace/drv/bus/usb/ohci/ohci_rh.c

    r65c059f rc21e6a5  
    182182        batch->error = virthub_base_request(&instance->base, batch->target,
    183183            batch->dir, &batch->setup.packet,
    184             batch->buffer, batch->buffer_size, &batch->transferred_size);
     184            batch->dma_buffer.virt, batch->buffer_size, &batch->transferred_size);
    185185        if (batch->error == ENAK) {
    186186                /* Lock the HC guard */
     
    233233                batch->error = virthub_base_request(&instance->base, batch->target,
    234234                    batch->dir, &batch->setup.packet,
    235                     batch->buffer, batch->buffer_size, &batch->transferred_size);
     235                    batch->dma_buffer.virt, batch->buffer_size, &batch->transferred_size);
    236236                usb_transfer_batch_finish(batch);
    237237        }
  • uspace/drv/bus/usb/uhci/uhci_batch.c

    r65c059f rc21e6a5  
    6161{
    6262        assert(uhci_batch);
    63         free32(uhci_batch->device_buffer);
     63        dma_buffer_free(&uhci_batch->uhci_dma_buffer);
    6464        free(uhci_batch);
    6565}
     
    110110
    111111        const size_t total_size = (sizeof(td_t) * uhci_batch->td_count)
    112             + sizeof(qh_t) + setup_size + usb_batch->buffer_size;
    113         uhci_batch->device_buffer = malloc32(total_size);
    114         if (!uhci_batch->device_buffer) {
     112            + sizeof(qh_t) + setup_size;
     113
     114        if (dma_buffer_alloc(&uhci_batch->uhci_dma_buffer, total_size)) {
    115115                usb_log_error("Failed to allocate UHCI buffer.");
    116116                return ENOMEM;
    117117        }
    118         memset(uhci_batch->device_buffer, 0, total_size);
    119 
    120         uhci_batch->tds = uhci_batch->device_buffer;
    121         uhci_batch->qh =
    122             (uhci_batch->device_buffer + (sizeof(td_t) * uhci_batch->td_count));
     118        memset(uhci_batch->uhci_dma_buffer.virt, 0, total_size);
     119
     120        uhci_batch->tds = uhci_batch->uhci_dma_buffer.virt;
     121        uhci_batch->qh = (qh_t *) &uhci_batch->tds[uhci_batch->td_count];
    123122
    124123        qh_init(uhci_batch->qh);
    125124        qh_set_element_td(uhci_batch->qh, &uhci_batch->tds[0]);
    126125
    127         void *dest =
    128             uhci_batch->device_buffer + (sizeof(td_t) * uhci_batch->td_count)
    129             + sizeof(qh_t);
     126        void *setup_buffer = uhci_transfer_batch_setup_buffer(uhci_batch);
     127        assert(setup_buffer == (void *) (uhci_batch->qh + 1));
    130128        /* Copy SETUP packet data to the device buffer */
    131         memcpy(dest, usb_batch->setup.buffer, setup_size);
    132         dest += setup_size;
    133         /* Copy generic data unless they are provided by the device */
    134         if (usb_batch->dir != USB_DIRECTION_IN) {
    135                 memcpy(dest, usb_batch->buffer, usb_batch->buffer_size);
    136         }
     129        memcpy(setup_buffer, usb_batch->setup.buffer, setup_size);
     130
    137131        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT
    138132            " memory structures ready.", usb_batch,
     
    196190        }
    197191
    198         if (batch->dir == USB_DIRECTION_IN) {
    199                 assert(batch->transferred_size <= batch->buffer_size);
    200                 memcpy(batch->buffer,
    201                     uhci_transfer_batch_data_buffer(uhci_batch),
    202                     batch->transferred_size);
    203         }
     192        assert(batch->transferred_size <= batch->buffer_size);
    204193
    205194        return true;
  • uspace/drv/bus/usb/uhci/uhci_batch.h

    r65c059f rc21e6a5  
    6161        /** Number of TDs used by the transfer */
    6262        size_t td_count;
    63         /** Data buffer, must be accessible by the UHCI hw */
    64         void *device_buffer;
     63        /* Setup data */
     64        char *setup_buffer;
     65        /** Backing TDs + setup_buffer */
     66        dma_buffer_t uhci_dma_buffer;
    6567        /** List element */
    6668        link_t link;
     
    8082{
    8183        assert(uhci_batch);
    82         assert(uhci_batch->device_buffer);
    83         return uhci_batch->device_buffer + sizeof(qh_t) +
     84        return uhci_batch->uhci_dma_buffer.virt + sizeof(qh_t) +
    8485            uhci_batch->td_count * sizeof(td_t);
    8586}
     
    9394{
    9495        assert(uhci_batch);
    95         return uhci_transfer_batch_setup_buffer(uhci_batch) +
    96             (uhci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL ? USB_SETUP_PACKET_SIZE : 0);
     96        return uhci_batch->base.dma_buffer.virt;
    9797}
    9898
  • uspace/drv/bus/usb/uhci/uhci_rh.c

    r65c059f rc21e6a5  
    107107                batch->error = virthub_base_request(&instance->base, batch->target,
    108108                    batch->dir, (void*) batch->setup.buffer,
    109                     batch->buffer, batch->buffer_size, &batch->transferred_size);
     109                    batch->dma_buffer.virt, batch->buffer_size, &batch->transferred_size);
    110110                if (batch->error == ENAK)
    111111                        async_usleep(instance->base.endpoint_descriptor.poll_interval * 1000);
  • uspace/drv/bus/usb/vhc/transfer.c

    r65c059f rc21e6a5  
    7272                        rc = usbvirt_control_read(dev,
    7373                            batch->setup.buffer, USB_SETUP_PACKET_SIZE,
    74                             batch->buffer, batch->buffer_size,
     74                            batch->dma_buffer.virt, batch->buffer_size,
    7575                            actual_data_size);
    7676                } else {
     
    7878                        rc = usbvirt_control_write(dev,
    7979                            batch->setup.buffer, USB_SETUP_PACKET_SIZE,
    80                             batch->buffer, batch->buffer_size);
     80                            batch->dma_buffer.virt, batch->buffer_size);
    8181                }
    8282        } else {
     
    8484                        rc = usbvirt_data_in(dev, batch->ep->transfer_type,
    8585                            batch->ep->endpoint,
    86                             batch->buffer, batch->buffer_size,
     86                            batch->dma_buffer.virt, batch->buffer_size,
    8787                            actual_data_size);
    8888                } else {
     
    9090                        rc = usbvirt_data_out(dev, batch->ep->transfer_type,
    9191                            batch->ep->endpoint,
    92                             batch->buffer, batch->buffer_size);
     92                            batch->dma_buffer.virt, batch->buffer_size);
    9393                }
    9494        }
     
    108108                        rc = usbvirt_ipc_send_control_read(sess,
    109109                            batch->setup.buffer, USB_SETUP_PACKET_SIZE,
    110                             batch->buffer, batch->buffer_size,
     110                            batch->dma_buffer.virt, batch->buffer_size,
    111111                            actual_data_size);
    112112                } else {
     
    114114                        rc = usbvirt_ipc_send_control_write(sess,
    115115                            batch->setup.buffer, USB_SETUP_PACKET_SIZE,
    116                             batch->buffer, batch->buffer_size);
     116                            batch->dma_buffer.virt, batch->buffer_size);
    117117                }
    118118        } else {
     
    120120                        rc = usbvirt_ipc_send_data_in(sess, batch->ep->endpoint,
    121121                            batch->ep->transfer_type,
    122                             batch->buffer, batch->buffer_size,
     122                            batch->dma_buffer.virt, batch->buffer_size,
    123123                            actual_data_size);
    124124                } else {
     
    126126                        rc = usbvirt_ipc_send_data_out(sess, batch->ep->endpoint,
    127127                            batch->ep->transfer_type,
    128                             batch->buffer, batch->buffer_size);
     128                            batch->dma_buffer.virt, batch->buffer_size);
    129129                }
    130130        }
  • uspace/drv/bus/usb/xhci/commands.c

    r65c059f rc21e6a5  
    260260        // Prevent others from starting CR again.
    261261        cr_set_state(cr, XHCI_CR_STATE_CLOSED);
     262
     263        XHCI_REG_SET(hc->op_regs, XHCI_OP_CS, 1);
    262264        fibril_mutex_unlock(&cr->guard);
    263265}
  • uspace/drv/bus/usb/xhci/hc.c

    r65c059f rc21e6a5  
    476476                return ETIMEOUT;
    477477
    478         uint64_t dcbaaptr = hc->dcbaa_dma.phys;
    479         XHCI_REG_WR(hc->op_regs, XHCI_OP_DCBAAP, dcbaaptr);
     478        XHCI_REG_WR(hc->op_regs, XHCI_OP_DCBAAP, hc->dcbaa_dma.phys);
    480479        XHCI_REG_WR(hc->op_regs, XHCI_OP_MAX_SLOTS_EN, hc->max_slots);
    481480
  • uspace/drv/bus/usb/xhci/isoch.c

    r65c059f rc21e6a5  
    480480        xhci_isoch_t * const isoch = ep->isoch;
    481481
    482         if (transfer->batch.buffer_size > ep->base.max_transfer_size) {
    483                 usb_log_error("Cannot schedule an oversized isochronous transfer.");
    484                 return ELIMIT;
    485         }
     482        /* This shall be already checked by endpoint */
     483        assert(transfer->batch.buffer_size <= ep->base.max_transfer_size);
    486484
    487485        fibril_mutex_lock(&isoch->guard);
     
    524522        /* Prepare the transfer. */
    525523        it->size = transfer->batch.buffer_size;
    526         memcpy(it->data.virt, transfer->batch.buffer, it->size);
     524        memcpy(it->data.virt, transfer->batch.dma_buffer.virt, it->size);
    527525        it->state = ISOCH_FILLED;
    528526
     
    573571        /* Withdraw results from previous transfer. */
    574572        if (!it->error) {
    575                 memcpy(transfer->batch.buffer, it->data.virt, it->size);
     573                memcpy(transfer->batch.dma_buffer.virt, it->data.virt, it->size);
    576574                transfer->batch.transferred_size = it->size;
    577575                transfer->batch.error = it->error;
  • uspace/drv/bus/usb/xhci/transfers.c

    r65c059f rc21e6a5  
    115115{
    116116        xhci_transfer_t *transfer = xhci_transfer_from_batch(batch);
    117 
    118         dma_buffer_free(&transfer->hc_buffer);
    119117        free(transfer);
    120118}
     
    135133        size_t i, size_t total, size_t *remaining)
    136134{
    137         const uintptr_t ptr = dma_buffer_phys(&transfer->hc_buffer,
    138                 transfer->hc_buffer.virt + i * PAGE_SIZE);
     135        const uintptr_t ptr = dma_buffer_phys(&transfer->batch.dma_buffer,
     136                transfer->batch.dma_buffer.virt + i * PAGE_SIZE);
    139137
    140138        trb->parameter = host2xhci(64, ptr);
     
    418416        }
    419417
    420         if (batch->dir == USB_DIRECTION_IN) {
    421                 assert(batch->buffer);
    422                 assert(batch->transferred_size <= batch->buffer_size);
    423                 memcpy(batch->buffer, transfer->hc_buffer.virt, batch->transferred_size);
    424         }
     418        assert(batch->transferred_size <= batch->buffer_size);
    425419
    426420        usb_transfer_batch_finish(batch);
     
    472466        const usb_transfer_type_t type = batch->ep->transfer_type;
    473467        assert(transfer_handlers[type]);
    474 
    475         if (batch->buffer_size > 0) {
    476                 if (dma_buffer_alloc(&transfer->hc_buffer, batch->buffer_size))
    477                         return ENOMEM;
    478         }
    479 
    480         if (batch->dir != USB_DIRECTION_IN) {
    481                 // Sending stuff from host to device, we need to copy the actual data.
    482                 memcpy(transfer->hc_buffer.virt, batch->buffer, batch->buffer_size);
    483         }
    484468
    485469        /*
  • uspace/drv/bus/usb/xhci/transfers.h

    r65c059f rc21e6a5  
    5050        uint8_t direction;
    5151
    52         dma_buffer_t hc_buffer;
    53 
    5452        uintptr_t interrupt_trb_phys;
    5553} xhci_transfer_t;
  • uspace/lib/drv/generic/remote_usbhc.c

    r65c059f rc21e6a5  
    428428                return err;
    429429
     430        /*
     431         * As we're going to check the mapping, we must make sure the memory is
     432         * actually mapped. We must do it right now, because the area might be
     433         * read-only or write-only, and we may be unsure later.
     434         */
     435        if (flags & AS_AREA_READ) {
     436                char foo = 0;
     437                volatile const char *buf = trans->buffer;
     438                for (size_t i = 0; i < size; i += PAGE_SIZE)
     439                        foo += buf[i];
     440        } else {
     441                volatile char *buf = trans->buffer;
     442                for (size_t i = 0; i < size; i += PAGE_SIZE)
     443                        buf[i] = 0xff;
     444        }
     445
    430446        return EOK;
    431447}
  • uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h

    r65c059f rc21e6a5  
    4141#include <stddef.h>
    4242#include <stdint.h>
     43#include <usb/dma_buffer.h>
    4344#include <usb/request.h>
    4445#include <usb/usb.h>
     
    5657        /** Target for communication */
    5758        usb_target_t target;
     59        /** Direction of the transfer */
     60        usb_direction_t dir;
    5861
    5962        /** Endpoint used for communication */
    6063        endpoint_t *ep;
    61 
    62         /** Direction of the transfer */
    63         usb_direction_t dir;
    64 
    65         /** Function called on completion */
    66         usbhc_iface_transfer_callback_t on_complete;
    67         /** Arbitrary data for the handler */
    68         void *on_complete_data;
    6964
    7065        /** Place to store SETUP data needed by control transfers */
     
    7570        } setup;
    7671
    77         /** Place for data to send/receive */
    78         char *buffer;
    79         /** Size of memory pointed to by buffer member */
     72        /** DMA buffer with enforced policy */
     73        dma_buffer_t dma_buffer;
     74        /** Size of memory buffer */
    8075        size_t buffer_size;
     76
     77        /**
     78         * In case the DMA buffer is allocated, the original buffer must to be
     79         * stored to be filled after the IN transaction is finished.
     80         */
     81        char *original_buffer;
     82
     83        /** Indicates success/failure of the communication */
     84        errno_t error;
    8185        /** Actually used portion of the buffer */
    8286        size_t transferred_size;
    8387
    84         /** Indicates success/failure of the communication */
    85         errno_t error;
     88        /** Function called on completion */
     89        usbhc_iface_transfer_callback_t on_complete;
     90        /** Arbitrary data for the handler */
     91        void *on_complete_data;
    8692} usb_transfer_batch_t;
    8793
     
    108114void usb_transfer_batch_init(usb_transfer_batch_t *, endpoint_t *);
    109115
     116/** Buffer preparation */
     117errno_t usb_transfer_batch_prepare_buffer(usb_transfer_batch_t *, char *);
     118
    110119/** Batch finalization. */
    111120void usb_transfer_batch_finish(usb_transfer_batch_t *);
  • uspace/lib/usbhost/src/endpoint.c

    r65c059f rc21e6a5  
    7474
    7575        ep->max_transfer_size = ep->max_packet_size * ep->packets_per_uframe;
     76        ep->transfer_buffer_policy = DMA_POLICY_STRICT;
    7677}
    7778
     
    215216 * @param name Communication identifier (for nicer output).
    216217 */
    217 int endpoint_send_batch(endpoint_t *ep, usb_target_t target,
     218errno_t endpoint_send_batch(endpoint_t *ep, usb_target_t target,
    218219    usb_direction_t direction, char *data, size_t size, uint64_t setup_data,
    219220    usbhc_iface_transfer_callback_t on_complete, void *arg, const char *name)
     
    258259
    259260        batch->target = target;
    260         batch->buffer = data;
    261         batch->buffer_size = size;
    262261        batch->setup.packed = setup_data;
    263262        batch->dir = direction;
     263        batch->buffer_size = size;
     264
     265        errno_t err;
     266        if ((err = usb_transfer_batch_prepare_buffer(batch, data))) {
     267                usb_log_warning("Failed to prepare buffer for batch: %s", str_error(err));
     268                usb_transfer_batch_destroy(batch);
     269                return err;
     270        }
     271
    264272        batch->on_complete = on_complete;
    265273        batch->on_complete_data = arg;
  • uspace/lib/usbhost/src/usb_transfer_batch.c

    r65c059f rc21e6a5  
    104104
    105105/**
     106 * Prepare a DMA buffer according to endpoint policy.
     107 *
     108 * If the buffer is suitable to be used directly, it is. Otherwise, a bounce
     109 * buffer is created.
     110 */
     111errno_t usb_transfer_batch_prepare_buffer(
     112    usb_transfer_batch_t *batch, char *buf)
     113{
     114        const dma_policy_t policy = batch->ep->transfer_buffer_policy;
     115
     116        /* Empty transfers do not need a buffer */
     117        if (batch->buffer_size == 0)
     118                return EOK;
     119
     120        if (dma_buffer_check_policy(buf, batch->buffer_size, policy)) {
     121                /* Mark this case with invalid address */
     122                batch->original_buffer = NULL;
     123
     124                /* Fill the buffer with virtual address and lock it for DMA */
     125                return dma_buffer_lock(&batch->dma_buffer, buf, batch->buffer_size);
     126        }
     127        else {
     128                usb_log_debug("Batch(%p): Buffer cannot be used directly, "
     129                    "falling back to bounce buffer!", batch);
     130                const errno_t err = dma_buffer_alloc_policy(&batch->dma_buffer,
     131                    batch->buffer_size, policy);
     132
     133                /* Copy the data out */
     134                if (!err && batch->dir == USB_DIRECTION_OUT)
     135                        memcpy(batch->dma_buffer.virt, buf, batch->buffer_size);
     136
     137                /* Store the buffer to store the data back before finishing */
     138                batch->original_buffer = buf;
     139
     140                return err;
     141        }
     142}
     143
     144/**
    106145 * Finish a transfer batch: call handler, destroy batch, release endpoint.
    107146 *
     
    116155            batch, USB_TRANSFER_BATCH_ARGS(*batch));
    117156
     157        if (batch->error == EOK && batch->buffer_size > 0) {
     158                if (batch->original_buffer == NULL) {
     159                        /* Unlock the buffer for DMA */
     160                        dma_buffer_unlock(&batch->dma_buffer,
     161                            batch->buffer_size);
     162                }
     163                else {
     164                        /* We we're forced to use bounce buffer, copy it back */
     165                        if (batch->dir == USB_DIRECTION_IN)
     166                                memcpy(batch->original_buffer,
     167                                    batch->dma_buffer.virt,
     168                                    batch->transferred_size);
     169
     170                        dma_buffer_free(&batch->dma_buffer);
     171                }
     172        }
     173
    118174        if (batch->on_complete) {
    119175                const int err = batch->on_complete(batch->on_complete_data, batch->error, batch->transferred_size);
    120176                if (err)
    121                         usb_log_warning("batch %p failed to complete: %s",
     177                        usb_log_warning("Batch %p failed to complete: %s",
    122178                            batch, str_error(err));
    123179        }
Note: See TracChangeset for help on using the changeset viewer.