Changeset df6ded8 in mainline for uspace/drv/bus/usb/uhci/uhci_batch.c


Ignore:
Timestamp:
2018-02-28T16:37:50Z (6 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1b20da0
Parents:
f5e5f73 (diff), b2dca8de (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Jakub Jermar <jakub@…> (2018-02-28 16:06:42)
git-committer:
Jakub Jermar <jakub@…> (2018-02-28 16:37:50)
Message:

Merge github.com:helenos-xhci-team/helenos

This commit merges support for USB 3 and generally refactors, fixes,
extends and cleans up the existing USB framework.

Notable additions and features:

  • new host controller driver has been implemented to control various xHC models (among others, NEC Renesas uPD720200)
  • isochronous data transfer mode
  • support for explicit USB device removal
  • USB tablet driver
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/uhci/uhci_batch.c

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    4647
    4748#include "uhci_batch.h"
     49#include "hc.h"
    4850#include "hw_struct/transfer_descriptor.h"
    4951
    5052#define DEFAULT_ERROR_COUNT 3
    5153
    52 /** Safely destructs uhci_transfer_batch_t structure.
     54/** Transfer batch setup table. */
     55static void (*const batch_setup[])(uhci_transfer_batch_t*);
     56
     57/** Destroys uhci_transfer_batch_t structure.
    5358 *
    5459 * @param[in] uhci_batch Instance to destroy.
    5560 */
    56 static void uhci_transfer_batch_dispose(uhci_transfer_batch_t *uhci_batch)
    57 {
    58         if (uhci_batch) {
    59                 usb_transfer_batch_destroy(uhci_batch->usb_batch);
    60                 free32(uhci_batch->device_buffer);
    61                 free(uhci_batch);
    62         }
    63 }
    64 
    65 /** Finishes usb_transfer_batch and destroys the structure.
    66  *
    67  * @param[in] uhci_batch Instance to finish and destroy.
    68  */
    69 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch)
     61void uhci_transfer_batch_destroy(uhci_transfer_batch_t *uhci_batch)
    7062{
    7163        assert(uhci_batch);
    72         assert(uhci_batch->usb_batch);
    73         assert(!link_in_use(&uhci_batch->link));
    74         usb_transfer_batch_finish(uhci_batch->usb_batch,
    75             uhci_transfer_batch_data_buffer(uhci_batch));
    76         uhci_transfer_batch_dispose(uhci_batch);
    77 }
    78 
    79 /** Transfer batch setup table. */
    80 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t);
     64        dma_buffer_free(&uhci_batch->uhci_dma_buffer);
     65        free(uhci_batch);
     66}
    8167
    8268/** Allocate memory and initialize internal data structure.
     
    8571 * @return Valid pointer if all structures were successfully created,
    8672 * NULL otherwise.
     73 */
     74uhci_transfer_batch_t * uhci_transfer_batch_create(endpoint_t *ep)
     75{
     76        uhci_transfer_batch_t *uhci_batch =
     77            calloc(1, sizeof(uhci_transfer_batch_t));
     78        if (!uhci_batch) {
     79                usb_log_error("Failed to allocate UHCI batch.");
     80                return NULL;
     81        }
     82
     83        usb_transfer_batch_init(&uhci_batch->base, ep);
     84
     85        link_initialize(&uhci_batch->link);
     86        return uhci_batch;
     87}
     88
     89/* Prepares batch for commiting.
    8790 *
    8891 * Determines the number of needed transfer descriptors (TDs).
     
    9093 * Initializes parameters needed for the transfer and callback.
    9194 */
    92 uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *usb_batch)
     95int uhci_transfer_batch_prepare(uhci_transfer_batch_t *uhci_batch)
    9396{
    9497        static_assert((sizeof(td_t) % 16) == 0);
    95 #define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
    96         if (ptr == NULL) { \
    97                 usb_log_error(message); \
    98                 uhci_transfer_batch_dispose(uhci_batch); \
    99                 return NULL; \
    100         } else (void)0
    101 
    102         uhci_transfer_batch_t *uhci_batch =
    103             calloc(1, sizeof(uhci_transfer_batch_t));
    104         CHECK_NULL_DISPOSE_RETURN(uhci_batch,
    105             "Failed to allocate UHCI batch.\n");
    106         link_initialize(&uhci_batch->link);
    107         uhci_batch->td_count =
    108             (usb_batch->buffer_size + usb_batch->ep->max_packet_size - 1)
    109             / usb_batch->ep->max_packet_size;
     98
     99        usb_transfer_batch_t *usb_batch = &uhci_batch->base;
     100
     101        uhci_batch->td_count = (usb_batch->size + usb_batch->ep->max_packet_size - 1)
     102                / usb_batch->ep->max_packet_size;
     103
    110104        if (usb_batch->ep->transfer_type == USB_TRANSFER_CONTROL) {
    111105                uhci_batch->td_count += 2;
    112106        }
    113107
     108        const size_t setup_size = (usb_batch->ep->transfer_type == USB_TRANSFER_CONTROL)
     109                ? USB_SETUP_PACKET_SIZE
     110                : 0;
     111
    114112        const size_t total_size = (sizeof(td_t) * uhci_batch->td_count)
    115             + sizeof(qh_t) + usb_batch->setup_size + usb_batch->buffer_size;
    116         uhci_batch->device_buffer = malloc32(total_size);
    117         CHECK_NULL_DISPOSE_RETURN(uhci_batch->device_buffer,
    118             "Failed to allocate UHCI buffer.\n");
    119         memset(uhci_batch->device_buffer, 0, total_size);
    120 
    121         uhci_batch->tds = uhci_batch->device_buffer;
    122         uhci_batch->qh =
    123             (uhci_batch->device_buffer + (sizeof(td_t) * uhci_batch->td_count));
     113            + sizeof(qh_t) + setup_size;
     114
     115        if (dma_buffer_alloc(&uhci_batch->uhci_dma_buffer, total_size)) {
     116                usb_log_error("Failed to allocate UHCI buffer.");
     117                return ENOMEM;
     118        }
     119        memset(uhci_batch->uhci_dma_buffer.virt, 0, total_size);
     120
     121        uhci_batch->tds = uhci_batch->uhci_dma_buffer.virt;
     122        uhci_batch->qh = (qh_t *) &uhci_batch->tds[uhci_batch->td_count];
    124123
    125124        qh_init(uhci_batch->qh);
    126125        qh_set_element_td(uhci_batch->qh, &uhci_batch->tds[0]);
    127126
    128         void *dest =
    129             uhci_batch->device_buffer + (sizeof(td_t) * uhci_batch->td_count)
    130             + sizeof(qh_t);
     127        void *setup_buffer = uhci_transfer_batch_setup_buffer(uhci_batch);
     128        assert(setup_buffer == (void *) (uhci_batch->qh + 1));
    131129        /* Copy SETUP packet data to the device buffer */
    132         memcpy(dest, usb_batch->setup_buffer, usb_batch->setup_size);
    133         dest += usb_batch->setup_size;
    134         /* Copy generic data unless they are provided by the device */
    135         if (usb_batch->ep->direction != USB_DIRECTION_IN) {
    136                 memcpy(dest, usb_batch->buffer, usb_batch->buffer_size);
    137         }
    138         uhci_batch->usb_batch = usb_batch;
     130        memcpy(setup_buffer, usb_batch->setup.buffer, setup_size);
     131
    139132        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT
    140             " memory structures ready.\n", usb_batch,
     133            " memory structures ready.", usb_batch,
    141134            USB_TRANSFER_BATCH_ARGS(*usb_batch));
    142135
    143         const usb_direction_t dir = usb_transfer_batch_direction(usb_batch);
    144 
    145136        assert(batch_setup[usb_batch->ep->transfer_type]);
    146         batch_setup[usb_batch->ep->transfer_type](uhci_batch, dir);
    147 
    148         return uhci_batch;
     137        batch_setup[usb_batch->ep->transfer_type](uhci_batch);
     138
     139        return EOK;
    149140}
    150141
     
    158149 * is reached.
    159150 */
    160 bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch)
     151bool uhci_transfer_batch_check_completed(uhci_transfer_batch_t *uhci_batch)
    161152{
    162153        assert(uhci_batch);
    163         assert(uhci_batch->usb_batch);
     154        usb_transfer_batch_t *batch = &uhci_batch->base;
    164155
    165156        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT
    166             " checking %zu transfer(s) for completion.\n",
    167             uhci_batch->usb_batch,
    168             USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),
     157            " checking %zu transfer(s) for completion.",
     158            uhci_batch, USB_TRANSFER_BATCH_ARGS(*batch),
    169159            uhci_batch->td_count);
    170         uhci_batch->usb_batch->transfered_size = 0;
     160        batch->transferred_size = 0;
     161
     162        uhci_endpoint_t *uhci_ep = (uhci_endpoint_t *) batch->ep;
    171163
    172164        for (size_t i = 0;i < uhci_batch->td_count; ++i) {
     
    175167                }
    176168
    177                 uhci_batch->usb_batch->error = td_status(&uhci_batch->tds[i]);
    178                 if (uhci_batch->usb_batch->error != EOK) {
    179                         assert(uhci_batch->usb_batch->ep != NULL);
     169                batch->error = td_status(&uhci_batch->tds[i]);
     170                if (batch->error != EOK) {
     171                        assert(batch->ep != NULL);
    180172
    181173                        usb_log_debug("Batch %p found error TD(%zu->%p):%"
    182                             PRIx32 ".\n", uhci_batch->usb_batch, i,
     174                            PRIx32 ".", uhci_batch, i,
    183175                            &uhci_batch->tds[i], uhci_batch->tds[i].status);
    184176                        td_print_status(&uhci_batch->tds[i]);
    185177
    186                         endpoint_toggle_set(uhci_batch->usb_batch->ep,
    187                             td_toggle(&uhci_batch->tds[i]));
    188                         if (i > 0)
    189                                 goto substract_ret;
    190                         return true;
     178                        uhci_ep->toggle = td_toggle(&uhci_batch->tds[i]);
     179                        goto substract_ret;
    191180                }
    192181
    193                 uhci_batch->usb_batch->transfered_size
     182                batch->transferred_size
    194183                    += td_act_size(&uhci_batch->tds[i]);
    195184                if (td_is_short(&uhci_batch->tds[i]))
     
    197186        }
    198187substract_ret:
    199         uhci_batch->usb_batch->transfered_size
    200             -= uhci_batch->usb_batch->setup_size;
     188        if (batch->transferred_size > 0 && batch->ep->transfer_type == USB_TRANSFER_CONTROL) {
     189                assert(batch->transferred_size >= USB_SETUP_PACKET_SIZE);
     190                batch->transferred_size -= USB_SETUP_PACKET_SIZE;
     191        }
     192
     193        assert(batch->transferred_size <= batch->size);
     194
    201195        return true;
    202196}
     
    216210 * The last transfer is marked with IOC flag.
    217211 */
    218 static void batch_data(uhci_transfer_batch_t *uhci_batch, usb_direction_t dir)
     212static void batch_data(uhci_transfer_batch_t *uhci_batch)
    219213{
    220214        assert(uhci_batch);
    221         assert(uhci_batch->usb_batch);
    222         assert(uhci_batch->usb_batch->ep);
     215
     216        usb_direction_t dir = uhci_batch->base.dir;
    223217        assert(dir == USB_DIRECTION_OUT || dir == USB_DIRECTION_IN);
    224218
     
    226220        const usb_packet_id pid = direction_pids[dir];
    227221        const bool low_speed =
    228             uhci_batch->usb_batch->ep->speed == USB_SPEED_LOW;
    229         const size_t mps = uhci_batch->usb_batch->ep->max_packet_size;
    230         const usb_target_t target = {{
    231             uhci_batch->usb_batch->ep->address,
    232             uhci_batch->usb_batch->ep->endpoint }};
    233 
    234         int toggle = endpoint_toggle_get(uhci_batch->usb_batch->ep);
     222            uhci_batch->base.ep->device->speed == USB_SPEED_LOW;
     223        const size_t mps = uhci_batch->base.ep->max_packet_size;
     224
     225        uhci_endpoint_t *uhci_ep = (uhci_endpoint_t *) uhci_batch->base.ep;
     226
     227        int toggle = uhci_ep->toggle;
    235228        assert(toggle == 0 || toggle == 1);
    236229
    237230        size_t td = 0;
    238         size_t remain_size = uhci_batch->usb_batch->buffer_size;
     231        size_t remain_size = uhci_batch->base.size;
    239232        char *buffer = uhci_transfer_batch_data_buffer(uhci_batch);
    240233
     
    248241                td_init(
    249242                    &uhci_batch->tds[td], DEFAULT_ERROR_COUNT, packet_size,
    250                     toggle, false, low_speed, target, pid, buffer, next_td);
     243                    toggle, false, low_speed, uhci_batch->base.target, pid, buffer, next_td);
    251244
    252245                ++td;
     
    256249        }
    257250        td_set_ioc(&uhci_batch->tds[td - 1]);
    258         endpoint_toggle_set(uhci_batch->usb_batch->ep, toggle);
     251        uhci_ep->toggle = toggle;
    259252        usb_log_debug2(
    260             "Batch %p %s %s " USB_TRANSFER_BATCH_FMT " initialized.\n", \
    261             uhci_batch->usb_batch,
    262             usb_str_transfer_type(uhci_batch->usb_batch->ep->transfer_type),
    263             usb_str_direction(uhci_batch->usb_batch->ep->direction),
    264             USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch));
     253            "Batch %p %s %s " USB_TRANSFER_BATCH_FMT " initialized.", \
     254            uhci_batch,
     255            usb_str_transfer_type(uhci_batch->base.ep->transfer_type),
     256            usb_str_direction(uhci_batch->base.ep->direction),
     257            USB_TRANSFER_BATCH_ARGS(uhci_batch->base));
    265258}
    266259
     
    276269 * The last transfer is marked with IOC.
    277270 */
    278 static void batch_control(uhci_transfer_batch_t *uhci_batch, usb_direction_t dir)
     271static void batch_control(uhci_transfer_batch_t *uhci_batch)
    279272{
    280273        assert(uhci_batch);
    281         assert(uhci_batch->usb_batch);
    282         assert(uhci_batch->usb_batch->ep);
     274
     275        usb_direction_t dir = uhci_batch->base.dir;
    283276        assert(dir == USB_DIRECTION_OUT || dir == USB_DIRECTION_IN);
    284277        assert(uhci_batch->td_count >= 2);
     
    291284        const usb_packet_id status_stage_pid = status_stage_pids[dir];
    292285        const bool low_speed =
    293             uhci_batch->usb_batch->ep->speed == USB_SPEED_LOW;
    294         const size_t mps = uhci_batch->usb_batch->ep->max_packet_size;
    295         const usb_target_t target = {{
    296             uhci_batch->usb_batch->ep->address,
    297             uhci_batch->usb_batch->ep->endpoint }};
     286            uhci_batch->base.ep->device->speed == USB_SPEED_LOW;
     287        const size_t mps = uhci_batch->base.ep->max_packet_size;
     288        const usb_target_t target = uhci_batch->base.target;
    298289
    299290        /* setup stage */
    300291        td_init(
    301292            &uhci_batch->tds[0], DEFAULT_ERROR_COUNT,
    302             uhci_batch->usb_batch->setup_size, 0, false,
     293            USB_SETUP_PACKET_SIZE, 0, false,
    303294            low_speed, target, USB_PID_SETUP,
    304295            uhci_transfer_batch_setup_buffer(uhci_batch), &uhci_batch->tds[1]);
     
    307298        size_t td = 1;
    308299        unsigned toggle = 1;
    309         size_t remain_size = uhci_batch->usb_batch->buffer_size;
     300        size_t remain_size = uhci_batch->base.size;
    310301        char *buffer = uhci_transfer_batch_data_buffer(uhci_batch);
    311302
     
    333324        td_set_ioc(&uhci_batch->tds[td]);
    334325
    335         usb_log_debug2("Control last TD status: %x.\n",
     326        usb_log_debug2("Control last TD status: %x.",
    336327            uhci_batch->tds[td].status);
    337328}
    338329
    339 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t) =
     330static void (*const batch_setup[])(uhci_transfer_batch_t*) =
    340331{
    341332        [USB_TRANSFER_CONTROL] = batch_control,
Note: See TracChangeset for help on using the changeset viewer.