Ignore:
File:
1 edited

Legend:

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

    r910ca3f r06c552c  
    3030 */
    3131/** @file
    32  * @brief UHCI driver USB transfer structure
     32 * @brief UHCI driver USB transaction structure
    3333 */
    3434#include <errno.h>
     
    4848        qh_t *qh;
    4949        td_t *tds;
    50         size_t td_count;
     50        size_t transfers;
    5151} uhci_batch_t;
    5252
     
    6161 *
    6262 * @param[in] fun DDF function to pass to callback.
    63  * @param[in] ep Communication target
     63 * @param[in] target Device and endpoint target of the transaction.
     64 * @param[in] transfer_type Interrupt, Control or Bulk.
     65 * @param[in] max_packet_size maximum allowed size of data transfers.
     66 * @param[in] speed Speed of the transaction.
    6467 * @param[in] buffer Data source/destination.
    6568 * @param[in] size Size of the buffer.
    6669 * @param[in] setup_buffer Setup data source (if not NULL)
    6770 * @param[in] setup_size Size of setup_buffer (should be always 8)
    68  * @param[in] func_in function to call on inbound transfer completion
    69  * @param[in] func_out function to call on outbound transfer completion
     71 * @param[in] func_in function to call on inbound transaction completion
     72 * @param[in] func_out function to call on outbound transaction completion
    7073 * @param[in] arg additional parameter to func_in or func_out
     74 * @param[in] ep Pointer to endpoint toggle management structure.
    7175 * @return Valid pointer if all substructures were successfully created,
    7276 * NULL otherwise.
    7377 *
    74  * Determines the number of needed transfer descriptors (TDs).
    75  * Prepares a transport buffer (that is accessible by the hardware).
    76  * Initializes parameters needed for the transfer and callback.
     78 * Determines the number of needed transfers (TDs). Prepares a transport buffer
     79 * (that is accessible by the hardware). Initializes parameters needed for the
     80 * transaction and callback.
    7781 */
    7882usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
     
    99103        usb_target_t target =
    100104            { .address = ep->address, .endpoint = ep->endpoint };
    101         usb_transfer_batch_init(instance, ep,
    102             buffer, NULL, buffer_size, NULL, setup_size,
    103             func_in, func_out, arg, fun, NULL);
     105        usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed,
     106            ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
     107            func_in, func_out, arg, fun, ep, NULL);
    104108
    105109
     
    109113        instance->private_data = data;
    110114
    111         data->td_count =
     115        data->transfers =
    112116            (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
    113117        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
    114                 data->td_count += 2;
    115         }
    116 
    117         data->tds = malloc32(sizeof(td_t) * data->td_count);
     118                data->transfers += 2;
     119        }
     120
     121        data->tds = malloc32(sizeof(td_t) * data->transfers);
    118122        CHECK_NULL_DISPOSE_RETURN(
    119123            data->tds, "Failed to allocate transfer descriptors.\n");
    120         bzero(data->tds, sizeof(td_t) * data->td_count);
     124        bzero(data->tds, sizeof(td_t) * data->transfers);
    121125
    122126        data->qh = malloc32(sizeof(qh_t));
     
    127131
    128132        if (buffer_size > 0) {
    129                 instance->data_buffer = malloc32(buffer_size);
    130                 CHECK_NULL_DISPOSE_RETURN(instance->data_buffer,
     133                instance->transport_buffer = malloc32(buffer_size);
     134                CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
    131135                    "Failed to allocate device accessible buffer.\n");
    132136        }
     
    150154 *
    151155 * Walk all TDs. Stop with false if there is an active one (it is to be
    152  * processed). Stop with true if an error is found. Return true if the last TD
     156 * processed). Stop with true if an error is found. Return true if the last TS
    153157 * is reached.
    154158 */
     
    160164
    161165        usb_log_debug2("Batch(%p) checking %d transfer(s) for completion.\n",
    162             instance, data->td_count);
     166            instance, data->transfers);
    163167        instance->transfered_size = 0;
    164168        size_t i = 0;
    165         for (;i < data->td_count; ++i) {
     169        for (;i < data->transfers; ++i) {
    166170                if (td_is_active(&data->tds[i])) {
    167171                        return false;
     
    173177                            instance, i, data->tds[i].status);
    174178                        td_print_status(&data->tds[i]);
    175 
    176179                        assert(instance->ep != NULL);
     180
    177181                        endpoint_toggle_set(instance->ep,
    178182                            td_toggle(&data->tds[i]));
     
    191195}
    192196/*----------------------------------------------------------------------------*/
    193 /** Prepares control write transfer.
    194  *
    195  * @param[in] instance Batch structure to use.
    196  *
    197  * Uses generic control function with pids OUT and IN.
     197/** Prepares control write transaction.
     198 *
     199 * @param[in] instance Batch structure to use.
     200 *
     201 * Uses genercir control function with pids OUT and IN.
    198202 */
    199203void batch_control_write(usb_transfer_batch_t *instance)
     
    201205        assert(instance);
    202206        /* We are data out, we are supposed to provide data */
    203         memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     207        memcpy(instance->transport_buffer, instance->buffer,
     208            instance->buffer_size);
    204209        batch_control(instance, USB_PID_OUT, USB_PID_IN);
    205210        instance->next_step = batch_call_out_and_dispose;
     
    207212}
    208213/*----------------------------------------------------------------------------*/
    209 /** Prepares control read transfer.
     214/** Prepares control read transaction.
    210215 *
    211216 * @param[in] instance Batch structure to use.
     
    221226}
    222227/*----------------------------------------------------------------------------*/
    223 /** Prepare interrupt in transfer.
    224  *
    225  * @param[in] instance Batch structure to use.
    226  *
    227  * Data transfer with PID_IN.
     228/** Prepare interrupt in transaction.
     229 *
     230 * @param[in] instance Batch structure to use.
     231 *
     232 * Data transaction with PID_IN.
    228233 */
    229234void batch_interrupt_in(usb_transfer_batch_t *instance)
    230235{
    231236        assert(instance);
     237        instance->direction = USB_DIRECTION_IN;
    232238        batch_data(instance, USB_PID_IN);
    233239        instance->next_step = batch_call_in_and_dispose;
     
    235241}
    236242/*----------------------------------------------------------------------------*/
    237 /** Prepare interrupt out transfer.
    238  *
    239  * @param[in] instance Batch structure to use.
    240  *
    241  * Data transfer with PID_OUT.
     243/** Prepare interrupt out transaction.
     244 *
     245 * @param[in] instance Batch structure to use.
     246 *
     247 * Data transaction with PID_OUT.
    242248 */
    243249void batch_interrupt_out(usb_transfer_batch_t *instance)
    244250{
    245251        assert(instance);
     252        instance->direction = USB_DIRECTION_OUT;
    246253        /* We are data out, we are supposed to provide data */
    247         memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     254        memcpy(instance->transport_buffer, instance->buffer,
     255            instance->buffer_size);
    248256        batch_data(instance, USB_PID_OUT);
    249257        instance->next_step = batch_call_out_and_dispose;
     
    251259}
    252260/*----------------------------------------------------------------------------*/
    253 /** Prepare bulk in transfer.
    254  *
    255  * @param[in] instance Batch structure to use.
    256  *
    257  * Data transfer with PID_IN.
     261/** Prepare bulk in transaction.
     262 *
     263 * @param[in] instance Batch structure to use.
     264 *
     265 * Data transaction with PID_IN.
    258266 */
    259267void batch_bulk_in(usb_transfer_batch_t *instance)
     
    261269        assert(instance);
    262270        batch_data(instance, USB_PID_IN);
     271        instance->direction = USB_DIRECTION_IN;
    263272        instance->next_step = batch_call_in_and_dispose;
    264273        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    265274}
    266275/*----------------------------------------------------------------------------*/
    267 /** Prepare bulk out transfer.
    268  *
    269  * @param[in] instance Batch structure to use.
    270  *
    271  * Data transfer with PID_OUT.
     276/** Prepare bulk out transaction.
     277 *
     278 * @param[in] instance Batch structure to use.
     279 *
     280 * Data transaction with PID_OUT.
    272281 */
    273282void batch_bulk_out(usb_transfer_batch_t *instance)
    274283{
    275284        assert(instance);
     285        instance->direction = USB_DIRECTION_OUT;
    276286        /* We are data out, we are supposed to provide data */
    277         memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     287        memcpy(instance->transport_buffer, instance->buffer,
     288            instance->buffer_size);
    278289        batch_data(instance, USB_PID_OUT);
    279290        instance->next_step = batch_call_out_and_dispose;
     
    281292}
    282293/*----------------------------------------------------------------------------*/
    283 /** Prepare generic data transfer
    284  *
    285  * @param[in] instance Batch structure to use.
    286  * @param[in] pid Pid to use for data transactions.
    287  *
    288  * Transactions with alternating toggle bit and supplied pid value.
     294/** Prepare generic data transaction
     295 *
     296 * @param[in] instance Batch structure to use.
     297 * @param[in] pid Pid to use for data transfers.
     298 *
     299 * Packets with alternating toggle bit and supplied pid value.
    289300 * The last transfer is marked with IOC flag.
    290301 */
     
    295306        assert(data);
    296307
    297         const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
     308        const bool low_speed = instance->speed == USB_SPEED_LOW;
    298309        int toggle = endpoint_toggle_get(instance->ep);
    299310        assert(toggle == 0 || toggle == 1);
    300311
    301         size_t td = 0;
     312        size_t transfer = 0;
    302313        size_t remain_size = instance->buffer_size;
    303         char *buffer = instance->data_buffer;
    304314        while (remain_size > 0) {
     315                char *trans_data =
     316                    instance->transport_buffer + instance->buffer_size
     317                    - remain_size;
     318
    305319                const size_t packet_size =
    306                     (instance->ep->max_packet_size > remain_size) ?
    307                     remain_size : instance->ep->max_packet_size;
    308 
    309                 td_t *next_td = (td + 1 < data->td_count)
    310                     ? &data->tds[td + 1] : NULL;
    311 
    312 
    313                 usb_target_t target =
    314                     { instance->ep->address, instance->ep->endpoint };
    315 
    316                 assert(td < data->td_count);
     320                    (instance->max_packet_size > remain_size) ?
     321                    remain_size : instance->max_packet_size;
     322
     323                td_t *next_transfer = (transfer + 1 < data->transfers)
     324                    ? &data->tds[transfer + 1] : NULL;
     325
     326                assert(transfer < data->transfers);
     327                assert(packet_size <= remain_size);
     328
    317329                td_init(
    318                     &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
    319                     toggle, false, low_speed, target, pid, buffer, next_td);
    320 
    321                 ++td;
     330                    &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size,
     331                    toggle, false, low_speed, instance->target, pid, trans_data,
     332                    next_transfer);
     333
     334
    322335                toggle = 1 - toggle;
    323                 buffer += packet_size;
    324                 assert(packet_size <= remain_size);
    325336                remain_size -= packet_size;
    326         }
    327         td_set_ioc(&data->tds[td - 1]);
     337                ++transfer;
     338        }
     339        td_set_ioc(&data->tds[transfer - 1]);
    328340        endpoint_toggle_set(instance->ep, toggle);
    329341}
    330342/*----------------------------------------------------------------------------*/
    331 /** Prepare generic control transfer
    332  *
    333  * @param[in] instance Batch structure to use.
    334  * @param[in] data_stage Pid to use for data tds.
    335  * @param[in] status_stage Pid to use for data tds.
     343/** Prepare generic control transaction
     344 *
     345 * @param[in] instance Batch structure to use.
     346 * @param[in] data_stage Pid to use for data transfers.
     347 * @param[in] status_stage Pid to use for data transfers.
    336348 *
    337349 * Setup stage with toggle 0 and USB_PID_SETUP.
     
    346358        uhci_batch_t *data = instance->private_data;
    347359        assert(data);
    348         assert(data->td_count >= 2);
    349 
    350         const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
    351         const usb_target_t target =
    352             { instance->ep->address, instance->ep->endpoint };
    353 
     360        assert(data->transfers >= 2);
     361
     362        const bool low_speed = instance->speed == USB_SPEED_LOW;
     363        int toggle = 0;
    354364        /* setup stage */
    355365        td_init(
    356             data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, 0, false,
    357             low_speed, target, USB_PID_SETUP, instance->setup_buffer,
     366            data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, toggle, false,
     367            low_speed, instance->target, USB_PID_SETUP, instance->setup_buffer,
    358368            &data->tds[1]);
    359369
    360370        /* data stage */
    361         size_t td = 1;
    362         unsigned toggle = 1;
     371        size_t transfer = 1;
    363372        size_t remain_size = instance->buffer_size;
    364         char *buffer = instance->data_buffer;
    365373        while (remain_size > 0) {
     374                char *control_data =
     375                    instance->transport_buffer + instance->buffer_size
     376                    - remain_size;
     377
     378                toggle = 1 - toggle;
     379
    366380                const size_t packet_size =
    367                     (instance->ep->max_packet_size > remain_size) ?
    368                     remain_size : instance->ep->max_packet_size;
     381                    (instance->max_packet_size > remain_size) ?
     382                    remain_size : instance->max_packet_size;
    369383
    370384                td_init(
    371                     &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
    372                     toggle, false, low_speed, target, data_stage,
    373                     buffer, &data->tds[td + 1]);
    374 
    375                 ++td;
    376                 toggle = 1 - toggle;
    377                 buffer += packet_size;
    378                 assert(td < data->td_count);
     385                    &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size,
     386                    toggle, false, low_speed, instance->target, data_stage,
     387                    control_data, &data->tds[transfer + 1]);
     388
     389                ++transfer;
     390                assert(transfer < data->transfers);
    379391                assert(packet_size <= remain_size);
    380392                remain_size -= packet_size;
     
    382394
    383395        /* status stage */
    384         assert(td == data->td_count - 1);
     396        assert(transfer == data->transfers - 1);
    385397
    386398        td_init(
    387             &data->tds[td], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
    388             target, status_stage, NULL, NULL);
    389         td_set_ioc(&data->tds[td]);
     399            &data->tds[transfer], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
     400            instance->target, status_stage, NULL, NULL);
     401        td_set_ioc(&data->tds[transfer]);
    390402
    391403        usb_log_debug2("Control last TD status: %x.\n",
    392             data->tds[td].status);
     404            data->tds[transfer].status);
    393405}
    394406/*----------------------------------------------------------------------------*/
     
    401413}
    402414/*----------------------------------------------------------------------------*/
    403 /** Helper function, calls callback and correctly destroys batch structure.
     415/** Helper function calls callback and correctly disposes of batch structure.
    404416 *
    405417 * @param[in] instance Batch structure to use.
     
    412424}
    413425/*----------------------------------------------------------------------------*/
    414 /** Helper function calls callback and correctly destroys batch structure.
     426/** Helper function calls callback and correctly disposes of batch structure.
    415427 *
    416428 * @param[in] instance Batch structure to use.
     
    437449        free32(data->qh);
    438450        free32(instance->setup_buffer);
    439         free32(instance->data_buffer);
     451        free32(instance->transport_buffer);
    440452        free(data);
    441453        free(instance);
Note: See TracChangeset for help on using the changeset viewer.