Ignore:
File:
1 edited

Legend:

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

    ra60150a ra7e2f0d  
    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 */
    5976batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    6077    usb_transfer_type_t transfer_type, size_t max_packet_size,
     
    6986        assert(func_in != NULL || func_out != NULL);
    7087
     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
    7197        batch_t *instance = malloc(sizeof(batch_t));
    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         }
     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);
    83106
    84107        instance->packets = (size + max_packet_size - 1) / max_packet_size;
     
    88111
    89112        instance->tds = malloc32(sizeof(td_t) * instance->packets);
    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         }
     113        CHECK_NULL_DISPOSE_RETURN(
     114            instance->tds, "Failed to allocate transfer descriptors.\n");
    96115        bzero(instance->tds, sizeof(td_t) * instance->packets);
    97116
    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) {
     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");
    121129                memcpy(instance->setup_buffer, setup_buffer, setup_size);
    122130        }
    123131
     132
     133        link_initialize(&instance->link);
     134
    124135        instance->max_packet_size = max_packet_size;
    125 
    126         link_initialize(&instance->link);
    127 
    128136        instance->target = target;
    129137        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 
    136138        instance->buffer = buffer;
    137139        instance->buffer_size = size;
     
    142144        instance->manager = manager;
    143145
    144         queue_head_element_td(instance->qh, addr_to_phys(instance->tds));
     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
    145153        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
    146154            instance, target.address, target.endpoint);
     
    148156}
    149157/*----------------------------------------------------------------------------*/
     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 */
    150163bool batch_is_complete(batch_t *instance)
    151164{
     
    165178                            instance, i, instance->tds[i].status);
    166179
    167                         device_keeper_set_toggle(instance->manager, instance->target,
    168                             td_toggle(&instance->tds[i]));
     180                        device_keeper_set_toggle(instance->manager,
     181                            instance->target, td_toggle(&instance->tds[i]));
    169182                        if (i > 0)
    170183                                goto substract_ret;
     
    181194}
    182195/*----------------------------------------------------------------------------*/
     196/** Prepares control write transaction.
     197 *
     198 * @param[in] instance Batch structure to use.
     199 */
    183200void batch_control_write(batch_t *instance)
    184201{
    185202        assert(instance);
    186203        /* we are data out, we are supposed to provide data */
    187         memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
     204        memcpy(instance->transport_buffer, instance->buffer,
     205            instance->buffer_size);
    188206        batch_control(instance, USB_PID_OUT, USB_PID_IN);
    189207        instance->next_step = batch_call_out_and_dispose;
     
    192210}
    193211/*----------------------------------------------------------------------------*/
     212/** Prepares control read transaction.
     213 *
     214 * @param[in] instance Batch structure to use.
     215 */
    194216void batch_control_read(batch_t *instance)
    195217{
     
    201223}
    202224/*----------------------------------------------------------------------------*/
     225/** Prepares interrupt in transaction.
     226 *
     227 * @param[in] instance Batch structure to use.
     228 */
    203229void batch_interrupt_in(batch_t *instance)
    204230{
     
    210236}
    211237/*----------------------------------------------------------------------------*/
     238/** Prepares interrupt out transaction.
     239 *
     240 * @param[in] instance Batch structure to use.
     241 */
    212242void batch_interrupt_out(batch_t *instance)
    213243{
    214244        assert(instance);
     245        /* we are data out, we are supposed to provide data */
    215246        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    216247        batch_data(instance, USB_PID_OUT);
     
    220251}
    221252/*----------------------------------------------------------------------------*/
     253/** Prepares bulk in transaction.
     254 *
     255 * @param[in] instance Batch structure to use.
     256 */
    222257void batch_bulk_in(batch_t *instance)
    223258{
     
    229264}
    230265/*----------------------------------------------------------------------------*/
     266/** Prepares bulk out transaction.
     267 *
     268 * @param[in] instance Batch structure to use.
     269 */
    231270void batch_bulk_out(batch_t *instance)
    232271{
     
    239278}
    240279/*----------------------------------------------------------------------------*/
     280/** Prepares generic data transaction
     281 *
     282 * @param[in] instance Batch structure to use.
     283 * @param[in] pid to use for data packets.
     284 */
    241285void batch_data(batch_t *instance, usb_packet_id pid)
    242286{
    243287        assert(instance);
    244288        const bool low_speed = instance->speed == USB_SPEED_LOW;
    245         int toggle = device_keeper_get_toggle(instance->manager, instance->target);
     289        int toggle =
     290            device_keeper_get_toggle(instance->manager, instance->target);
    246291        assert(toggle == 0 || toggle == 1);
    247292
     
    253298                    - remain_size;
    254299
    255 
    256300                const size_t packet_size =
    257301                    (instance->max_packet_size > remain_size) ?
    258302                    remain_size : instance->max_packet_size;
    259303
    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]);
     304                td_t *next_packet = (packet + 1 < instance->packets)
     305                    ? &instance->tds[packet + 1] : NULL;
     306
     307                assert(packet < instance->packets);
     308                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
    264315
    265316                toggle = 1 - toggle;
     317                remain_size -= packet_size;
    266318                ++packet;
    267                 assert(packet <= instance->packets);
    268                 assert(packet_size <= remain_size);
    269                 remain_size -= packet_size;
    270319        }
    271320        device_keeper_set_toggle(instance->manager, instance->target, toggle);
    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 /*----------------------------------------------------------------------------*/
     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 */
    277329void batch_control(batch_t *instance,
    278330   usb_packet_id data_stage, usb_packet_id status_stage)
     
    301353                    remain_size : instance->max_packet_size;
    302354
    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]);
     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]);
    307359
    308360                ++packet;
     
    323375}
    324376/*----------------------------------------------------------------------------*/
     377/** Prepares data, gets error status and calls callback in.
     378 *
     379 * @param[in] instance Batch structure to use.
     380 */
    325381void batch_call_in(batch_t *instance)
    326382{
     
    328384        assert(instance->callback_in);
    329385
    330         memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size);
     386        /* we are data in, we need data */
     387        memcpy(instance->buffer, instance->transport_buffer,
     388            instance->buffer_size);
    331389
    332390        int err = instance->error;
     
    335393            instance->transfered_size);
    336394
    337         instance->callback_in(instance->fun,
    338             err, instance->transfered_size,
    339             instance->arg);
    340 }
    341 /*----------------------------------------------------------------------------*/
     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 */
    342403void batch_call_out(batch_t *instance)
    343404{
     
    352413}
    353414/*----------------------------------------------------------------------------*/
     415/** Prepares data, gets error status, calls callback in and dispose.
     416 *
     417 * @param[in] instance Batch structure to use.
     418 */
    354419void batch_call_in_and_dispose(batch_t *instance)
    355420{
     
    359424}
    360425/*----------------------------------------------------------------------------*/
     426/** Gets error status, calls callback out and dispose.
     427 *
     428 * @param[in] instance Batch structure to use.
     429 */
    361430void batch_call_out_and_dispose(batch_t *instance)
    362431{
     
    366435}
    367436/*----------------------------------------------------------------------------*/
     437/** Correctly disposes all used data structures.
     438 *
     439 * @param[in] instance Batch structure to use.
     440 */
    368441void batch_dispose(batch_t *instance)
    369442{
    370443        assert(instance);
    371444        usb_log_debug("Batch(%p) disposing.\n", instance);
     445        /* free32 is NULL safe */
    372446        free32(instance->tds);
    373447        free32(instance->qh);
Note: See TracChangeset for help on using the changeset viewer.