Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/uhci-hcd/batch.c

    ra7e2f0d ra60150a  
    5757
    5858
    59 /** Allocates memory and initializes internal data structures.
    60  *
    61  * @param[in] fun DDF function to pass to callback.
    62  * @param[in] target Device and endpoint target of the transaction.
    63  * @param[in] transfer_type Interrupt, Control or Bulk.
    64  * @param[in] max_packet_size maximum allowed size of data packets.
    65  * @param[in] speed Speed of the transaction.
    66  * @param[in] buffer Data source/destination.
    67  * @param[in] size Size of the buffer.
    68  * @param[in] setup_buffer Setup data source (if not NULL)
    69  * @param[in] setup_size Size of setup_buffer (should be always 8)
    70  * @param[in] func_in function to call on inbound transaction completion
    71  * @param[in] func_out function to call on outbound transaction completion
    72  * @param[in] arg additional parameter to func_in or func_out
    73  * @param[in] manager Pointer to toggle management structure.
    74  * @return False, if there is an active TD, true otherwise.
    75  */
    7659batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    7760    usb_transfer_type_t transfer_type, size_t max_packet_size,
     
    8669        assert(func_in != NULL || func_out != NULL);
    8770
    88 #define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
    89         if (ptr == NULL) { \
    90                 usb_log_error(message); \
    91                 if (instance) { \
    92                         batch_dispose(instance); \
    93                 } \
    94                 return NULL; \
    95         } else (void)0
    96 
    9771        batch_t *instance = malloc(sizeof(batch_t));
    98         CHECK_NULL_DISPOSE_RETURN(instance,
    99             "Failed to allocate batch instance.\n");
    100         bzero(instance, sizeof(batch_t));
    101 
    102         instance->qh = malloc32(sizeof(queue_head_t));
    103         CHECK_NULL_DISPOSE_RETURN(instance->qh,
    104             "Failed to allocate batch queue head.\n");
    105         queue_head_init(instance->qh);
     72        if (instance == NULL) {
     73                usb_log_error("Failed to allocate batch instance.\n");
     74                return NULL;
     75        }
     76
     77        instance->qh = queue_head_get();
     78        if (instance->qh == NULL) {
     79                usb_log_error("Failed to allocate queue head.\n");
     80                free(instance);
     81                return NULL;
     82        }
    10683
    10784        instance->packets = (size + max_packet_size - 1) / max_packet_size;
     
    11188
    11289        instance->tds = malloc32(sizeof(td_t) * instance->packets);
    113         CHECK_NULL_DISPOSE_RETURN(
    114             instance->tds, "Failed to allocate transfer descriptors.\n");
     90        if (instance->tds == NULL) {
     91                usb_log_error("Failed to allocate transfer descriptors.\n");
     92                queue_head_dispose(instance->qh);
     93                free(instance);
     94                return NULL;
     95        }
    11596        bzero(instance->tds, sizeof(td_t) * instance->packets);
    11697
    117 //      const size_t transport_size = max_packet_size * instance->packets;
    118 
    119         if (size > 0) {
    120                 instance->transport_buffer = malloc32(size);
    121                 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
    122                     "Failed to allocate device accessible buffer.\n");
    123         }
    124 
    125         if (setup_size > 0) {
    126                 instance->setup_buffer = malloc32(setup_size);
    127                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    128                     "Failed to allocate device accessible setup buffer.\n");
     98        const size_t transport_size = max_packet_size * instance->packets;
     99
     100        instance->transport_buffer =
     101           (size > 0) ? malloc32(transport_size) : NULL;
     102
     103        if ((size > 0) && (instance->transport_buffer == NULL)) {
     104                usb_log_error("Failed to allocate device accessible buffer.\n");
     105                queue_head_dispose(instance->qh);
     106                free32(instance->tds);
     107                free(instance);
     108                return NULL;
     109        }
     110
     111        instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL;
     112        if ((setup_size > 0) && (instance->setup_buffer == NULL)) {
     113                usb_log_error("Failed to allocate device accessible setup buffer.\n");
     114                queue_head_dispose(instance->qh);
     115                free32(instance->tds);
     116                free32(instance->transport_buffer);
     117                free(instance);
     118                return NULL;
     119        }
     120        if (instance->setup_buffer) {
    129121                memcpy(instance->setup_buffer, setup_buffer, setup_size);
    130122        }
    131123
     124        instance->max_packet_size = max_packet_size;
    132125
    133126        link_initialize(&instance->link);
    134127
    135         instance->max_packet_size = max_packet_size;
    136128        instance->target = target;
    137129        instance->transfer_type = transfer_type;
     130
     131        if (func_out)
     132                instance->callback_out = func_out;
     133        if (func_in)
     134                instance->callback_in = func_in;
     135
    138136        instance->buffer = buffer;
    139137        instance->buffer_size = size;
     
    144142        instance->manager = manager;
    145143
    146         if (func_out)
    147                 instance->callback_out = func_out;
    148         if (func_in)
    149                 instance->callback_in = func_in;
    150 
    151         queue_head_set_element_td(instance->qh, addr_to_phys(instance->tds));
    152 
     144        queue_head_element_td(instance->qh, addr_to_phys(instance->tds));
    153145        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
    154146            instance, target.address, target.endpoint);
     
    156148}
    157149/*----------------------------------------------------------------------------*/
    158 /** Checks batch TDs for activity.
    159  *
    160  * @param[in] instance Batch structure to use.
    161  * @return False, if there is an active TD, true otherwise.
    162  */
    163150bool batch_is_complete(batch_t *instance)
    164151{
     
    178165                            instance, i, instance->tds[i].status);
    179166
    180                         device_keeper_set_toggle(instance->manager,
    181                             instance->target, td_toggle(&instance->tds[i]));
     167                        device_keeper_set_toggle(instance->manager, instance->target,
     168                            td_toggle(&instance->tds[i]));
    182169                        if (i > 0)
    183170                                goto substract_ret;
     
    194181}
    195182/*----------------------------------------------------------------------------*/
    196 /** Prepares control write transaction.
    197  *
    198  * @param[in] instance Batch structure to use.
    199  */
    200183void batch_control_write(batch_t *instance)
    201184{
    202185        assert(instance);
    203186        /* we are data out, we are supposed to provide data */
    204         memcpy(instance->transport_buffer, instance->buffer,
    205             instance->buffer_size);
     187        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    206188        batch_control(instance, USB_PID_OUT, USB_PID_IN);
    207189        instance->next_step = batch_call_out_and_dispose;
     
    210192}
    211193/*----------------------------------------------------------------------------*/
    212 /** Prepares control read transaction.
    213  *
    214  * @param[in] instance Batch structure to use.
    215  */
    216194void batch_control_read(batch_t *instance)
    217195{
     
    223201}
    224202/*----------------------------------------------------------------------------*/
    225 /** Prepares interrupt in transaction.
    226  *
    227  * @param[in] instance Batch structure to use.
    228  */
    229203void batch_interrupt_in(batch_t *instance)
    230204{
     
    236210}
    237211/*----------------------------------------------------------------------------*/
    238 /** Prepares interrupt out transaction.
    239  *
    240  * @param[in] instance Batch structure to use.
    241  */
    242212void batch_interrupt_out(batch_t *instance)
    243213{
    244214        assert(instance);
    245         /* we are data out, we are supposed to provide data */
    246215        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    247216        batch_data(instance, USB_PID_OUT);
     
    251220}
    252221/*----------------------------------------------------------------------------*/
    253 /** Prepares bulk in transaction.
    254  *
    255  * @param[in] instance Batch structure to use.
    256  */
    257222void batch_bulk_in(batch_t *instance)
    258223{
     
    264229}
    265230/*----------------------------------------------------------------------------*/
    266 /** Prepares bulk out transaction.
    267  *
    268  * @param[in] instance Batch structure to use.
    269  */
    270231void batch_bulk_out(batch_t *instance)
    271232{
     
    278239}
    279240/*----------------------------------------------------------------------------*/
    280 /** Prepares generic data transaction
    281  *
    282  * @param[in] instance Batch structure to use.
    283  * @param[in] pid to use for data packets.
    284  */
    285241void batch_data(batch_t *instance, usb_packet_id pid)
    286242{
    287243        assert(instance);
    288244        const bool low_speed = instance->speed == USB_SPEED_LOW;
    289         int toggle =
    290             device_keeper_get_toggle(instance->manager, instance->target);
     245        int toggle = device_keeper_get_toggle(instance->manager, instance->target);
    291246        assert(toggle == 0 || toggle == 1);
    292247
     
    298253                    - remain_size;
    299254
     255
    300256                const size_t packet_size =
    301257                    (instance->max_packet_size > remain_size) ?
    302258                    remain_size : instance->max_packet_size;
    303259
    304                 td_t *next_packet = (packet + 1 < instance->packets)
    305                     ? &instance->tds[packet + 1] : NULL;
    306 
    307                 assert(packet < instance->packets);
     260                td_init(&instance->tds[packet],
     261                    DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,
     262                    instance->target, pid, data,
     263                    &instance->tds[packet + 1]);
     264
     265                toggle = 1 - toggle;
     266                ++packet;
     267                assert(packet <= instance->packets);
    308268                assert(packet_size <= remain_size);
    309 
    310                 td_init(
    311                     &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
    312                     toggle, false, low_speed, instance->target, pid, data,
    313                     next_packet);
    314 
    315 
    316                 toggle = 1 - toggle;
    317269                remain_size -= packet_size;
    318                 ++packet;
    319270        }
    320271        device_keeper_set_toggle(instance->manager, instance->target, toggle);
    321 }
    322 /*----------------------------------------------------------------------------*/
    323 /** Prepares generic control transaction
    324  *
    325  * @param[in] instance Batch structure to use.
    326  * @param[in] data_stage to use for data packets.
    327  * @param[in] status_stage to use for data packets.
    328  */
     272
     273        instance->tds[packet - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
     274        instance->tds[packet - 1].next = 0 | LINK_POINTER_TERMINATE_FLAG;
     275}
     276/*----------------------------------------------------------------------------*/
    329277void batch_control(batch_t *instance,
    330278   usb_packet_id data_stage, usb_packet_id status_stage)
     
    353301                    remain_size : instance->max_packet_size;
    354302
    355                 td_init(
    356                     &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
    357                     toggle, false, low_speed, instance->target, data_stage,
    358                     data, &instance->tds[packet + 1]);
     303                td_init(&instance->tds[packet],
     304                    DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,
     305                    instance->target, data_stage, data,
     306                    &instance->tds[packet + 1]);
    359307
    360308                ++packet;
     
    375323}
    376324/*----------------------------------------------------------------------------*/
    377 /** Prepares data, gets error status and calls callback in.
    378  *
    379  * @param[in] instance Batch structure to use.
    380  */
    381325void batch_call_in(batch_t *instance)
    382326{
     
    384328        assert(instance->callback_in);
    385329
    386         /* we are data in, we need data */
    387         memcpy(instance->buffer, instance->transport_buffer,
    388             instance->buffer_size);
     330        memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size);
    389331
    390332        int err = instance->error;
     
    393335            instance->transfered_size);
    394336
    395         instance->callback_in(
    396             instance->fun, err, instance->transfered_size, instance->arg);
    397 }
    398 /*----------------------------------------------------------------------------*/
    399 /** Gets error status and calls callback out.
    400  *
    401  * @param[in] instance Batch structure to use.
    402  */
     337        instance->callback_in(instance->fun,
     338            err, instance->transfered_size,
     339            instance->arg);
     340}
     341/*----------------------------------------------------------------------------*/
    403342void batch_call_out(batch_t *instance)
    404343{
     
    413352}
    414353/*----------------------------------------------------------------------------*/
    415 /** Prepares data, gets error status, calls callback in and dispose.
    416  *
    417  * @param[in] instance Batch structure to use.
    418  */
    419354void batch_call_in_and_dispose(batch_t *instance)
    420355{
     
    424359}
    425360/*----------------------------------------------------------------------------*/
    426 /** Gets error status, calls callback out and dispose.
    427  *
    428  * @param[in] instance Batch structure to use.
    429  */
    430361void batch_call_out_and_dispose(batch_t *instance)
    431362{
     
    435366}
    436367/*----------------------------------------------------------------------------*/
    437 /** Correctly disposes all used data structures.
    438  *
    439  * @param[in] instance Batch structure to use.
    440  */
    441368void batch_dispose(batch_t *instance)
    442369{
    443370        assert(instance);
    444371        usb_log_debug("Batch(%p) disposing.\n", instance);
    445         /* free32 is NULL safe */
    446372        free32(instance->tds);
    447373        free32(instance->qh);
Note: See TracChangeset for help on using the changeset viewer.