Ignore:
File:
1 edited

Legend:

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

    ra7e2f0d reae83aa  
    5454static void batch_call_in_and_dispose(batch_t *instance);
    5555static void batch_call_out_and_dispose(batch_t *instance);
    56 static void batch_dispose(batch_t *instance);
    57 
    58 
    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  */
     56
     57
    7658batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    7759    usb_transfer_type_t transfer_type, size_t max_packet_size,
     
    7961    char* setup_buffer, size_t setup_size,
    8062    usbhc_iface_transfer_in_callback_t func_in,
    81     usbhc_iface_transfer_out_callback_t func_out, void *arg,
    82     device_keeper_t *manager
    83     )
     63    usbhc_iface_transfer_out_callback_t func_out, void *arg)
    8464{
    8565        assert(func_in == NULL || func_out == NULL);
    8666        assert(func_in != NULL || func_out != NULL);
    8767
    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 
    9768        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);
     69        if (instance == NULL) {
     70                usb_log_error("Failed to allocate batch instance.\n");
     71                return NULL;
     72        }
     73
     74        instance->qh = queue_head_get();
     75        if (instance->qh == NULL) {
     76                usb_log_error("Failed to allocate queue head.\n");
     77                free(instance);
     78                return NULL;
     79        }
    10680
    10781        instance->packets = (size + max_packet_size - 1) / max_packet_size;
     
    11185
    11286        instance->tds = malloc32(sizeof(td_t) * instance->packets);
    113         CHECK_NULL_DISPOSE_RETURN(
    114             instance->tds, "Failed to allocate transfer descriptors.\n");
     87        if (instance->tds == NULL) {
     88                usb_log_error("Failed to allocate transfer descriptors.\n");
     89                queue_head_dispose(instance->qh);
     90                free(instance);
     91                return NULL;
     92        }
    11593        bzero(instance->tds, sizeof(td_t) * instance->packets);
    11694
    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");
     95        const size_t transport_size = max_packet_size * instance->packets;
     96
     97        instance->transport_buffer =
     98           (size > 0) ? malloc32(transport_size) : NULL;
     99
     100        if ((size > 0) && (instance->transport_buffer == NULL)) {
     101                usb_log_error("Failed to allocate device accessible buffer.\n");
     102                queue_head_dispose(instance->qh);
     103                free32(instance->tds);
     104                free(instance);
     105                return NULL;
     106        }
     107
     108        instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL;
     109        if ((setup_size > 0) && (instance->setup_buffer == NULL)) {
     110                usb_log_error("Failed to allocate device accessible setup buffer.\n");
     111                queue_head_dispose(instance->qh);
     112                free32(instance->tds);
     113                free32(instance->transport_buffer);
     114                free(instance);
     115                return NULL;
     116        }
     117        if (instance->setup_buffer) {
    129118                memcpy(instance->setup_buffer, setup_buffer, setup_size);
    130119        }
    131120
     121        instance->max_packet_size = max_packet_size;
    132122
    133123        link_initialize(&instance->link);
    134124
    135         instance->max_packet_size = max_packet_size;
    136125        instance->target = target;
    137126        instance->transfer_type = transfer_type;
     127
     128        if (func_out)
     129                instance->callback_out = func_out;
     130        if (func_in)
     131                instance->callback_in = func_in;
     132
    138133        instance->buffer = buffer;
    139134        instance->buffer_size = size;
     
    142137        instance->arg = arg;
    143138        instance->speed = speed;
    144         instance->manager = manager;
    145 
    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 
     139
     140        queue_head_element_td(instance->qh, addr_to_phys(instance->tds));
    153141        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
    154142            instance, target.address, target.endpoint);
     
    156144}
    157145/*----------------------------------------------------------------------------*/
    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  */
    163146bool batch_is_complete(batch_t *instance)
    164147{
     
    177160                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    178161                            instance, i, instance->tds[i].status);
    179 
    180                         device_keeper_set_toggle(instance->manager,
    181                             instance->target, td_toggle(&instance->tds[i]));
    182162                        if (i > 0)
    183163                                goto substract_ret;
     
    194174}
    195175/*----------------------------------------------------------------------------*/
    196 /** Prepares control write transaction.
    197  *
    198  * @param[in] instance Batch structure to use.
    199  */
    200176void batch_control_write(batch_t *instance)
    201177{
    202178        assert(instance);
    203179        /* we are data out, we are supposed to provide data */
    204         memcpy(instance->transport_buffer, instance->buffer,
    205             instance->buffer_size);
     180        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    206181        batch_control(instance, USB_PID_OUT, USB_PID_IN);
    207182        instance->next_step = batch_call_out_and_dispose;
     
    210185}
    211186/*----------------------------------------------------------------------------*/
    212 /** Prepares control read transaction.
    213  *
    214  * @param[in] instance Batch structure to use.
    215  */
    216187void batch_control_read(batch_t *instance)
    217188{
     
    223194}
    224195/*----------------------------------------------------------------------------*/
    225 /** Prepares interrupt in transaction.
    226  *
    227  * @param[in] instance Batch structure to use.
    228  */
    229196void batch_interrupt_in(batch_t *instance)
    230197{
     
    236203}
    237204/*----------------------------------------------------------------------------*/
    238 /** Prepares interrupt out transaction.
    239  *
    240  * @param[in] instance Batch structure to use.
    241  */
    242205void batch_interrupt_out(batch_t *instance)
    243206{
    244207        assert(instance);
    245         /* we are data out, we are supposed to provide data */
    246208        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    247209        batch_data(instance, USB_PID_OUT);
     
    251213}
    252214/*----------------------------------------------------------------------------*/
    253 /** Prepares bulk in transaction.
    254  *
    255  * @param[in] instance Batch structure to use.
    256  */
    257215void batch_bulk_in(batch_t *instance)
    258216{
     
    264222}
    265223/*----------------------------------------------------------------------------*/
    266 /** Prepares bulk out transaction.
    267  *
    268  * @param[in] instance Batch structure to use.
    269  */
    270224void batch_bulk_out(batch_t *instance)
    271225{
     
    278232}
    279233/*----------------------------------------------------------------------------*/
    280 /** Prepares generic data transaction
    281  *
    282  * @param[in] instance Batch structure to use.
    283  * @param[in] pid to use for data packets.
    284  */
    285 void batch_data(batch_t *instance, usb_packet_id pid)
     234static void batch_data(batch_t *instance, usb_packet_id pid)
    286235{
    287236        assert(instance);
    288237        const bool low_speed = instance->speed == USB_SPEED_LOW;
    289         int toggle =
    290             device_keeper_get_toggle(instance->manager, instance->target);
    291         assert(toggle == 0 || toggle == 1);
     238        int toggle = 1;
    292239
    293240        size_t packet = 0;
     
    298245                    - remain_size;
    299246
     247                toggle = 1 - toggle;
     248
    300249                const size_t packet_size =
    301250                    (instance->max_packet_size > remain_size) ?
    302251                    remain_size : instance->max_packet_size;
    303252
    304                 td_t *next_packet = (packet + 1 < instance->packets)
    305                     ? &instance->tds[packet + 1] : NULL;
    306 
    307                 assert(packet < instance->packets);
     253                td_init(&instance->tds[packet],
     254                    DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,
     255                    instance->target, pid, data,
     256                    &instance->tds[packet + 1]);
     257
     258                ++packet;
     259                assert(packet <= instance->packets);
    308260                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;
    317261                remain_size -= packet_size;
    318                 ++packet;
    319         }
    320         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  */
    329 void batch_control(batch_t *instance,
     262        }
     263
     264        instance->tds[packet - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
     265        instance->tds[packet - 1].next = 0 | LINK_POINTER_TERMINATE_FLAG;
     266}
     267/*----------------------------------------------------------------------------*/
     268static void batch_control(batch_t *instance,
    330269   usb_packet_id data_stage, usb_packet_id status_stage)
    331270{
     
    353292                    remain_size : instance->max_packet_size;
    354293
    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]);
     294                td_init(&instance->tds[packet],
     295                    DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,
     296                    instance->target, data_stage, data,
     297                    &instance->tds[packet + 1]);
    359298
    360299                ++packet;
     
    375314}
    376315/*----------------------------------------------------------------------------*/
    377 /** Prepares data, gets error status and calls callback in.
    378  *
    379  * @param[in] instance Batch structure to use.
    380  */
    381316void batch_call_in(batch_t *instance)
    382317{
     
    384319        assert(instance->callback_in);
    385320
    386         /* we are data in, we need data */
    387         memcpy(instance->buffer, instance->transport_buffer,
    388             instance->buffer_size);
     321        memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size);
    389322
    390323        int err = instance->error;
     
    393326            instance->transfered_size);
    394327
    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  */
     328        instance->callback_in(instance->fun,
     329            err, instance->transfered_size,
     330            instance->arg);
     331}
     332/*----------------------------------------------------------------------------*/
    403333void batch_call_out(batch_t *instance)
    404334{
     
    413343}
    414344/*----------------------------------------------------------------------------*/
    415 /** Prepares data, gets error status, calls callback in and dispose.
    416  *
    417  * @param[in] instance Batch structure to use.
    418  */
    419345void batch_call_in_and_dispose(batch_t *instance)
    420346{
    421347        assert(instance);
    422348        batch_call_in(instance);
    423         batch_dispose(instance);
    424 }
    425 /*----------------------------------------------------------------------------*/
    426 /** Gets error status, calls callback out and dispose.
    427  *
    428  * @param[in] instance Batch structure to use.
    429  */
    430 void batch_call_out_and_dispose(batch_t *instance)
    431 {
    432         assert(instance);
    433         batch_call_out(instance);
    434         batch_dispose(instance);
    435 }
    436 /*----------------------------------------------------------------------------*/
    437 /** Correctly disposes all used data structures.
    438  *
    439  * @param[in] instance Batch structure to use.
    440  */
    441 void batch_dispose(batch_t *instance)
    442 {
    443         assert(instance);
    444349        usb_log_debug("Batch(%p) disposing.\n", instance);
    445         /* free32 is NULL safe */
    446350        free32(instance->tds);
    447351        free32(instance->qh);
     
    451355}
    452356/*----------------------------------------------------------------------------*/
     357void batch_call_out_and_dispose(batch_t *instance)
     358{
     359        assert(instance);
     360        batch_call_out(instance);
     361        usb_log_debug("Batch(%p) disposing.\n", instance);
     362        free32(instance->tds);
     363        free32(instance->qh);
     364        free32(instance->setup_buffer);
     365        free32(instance->transport_buffer);
     366        free(instance);
     367}
     368/*----------------------------------------------------------------------------*/
    453369int batch_schedule(batch_t *instance)
    454370{
Note: See TracChangeset for help on using the changeset viewer.