Changeset 62f4212 in mainline for uspace/drv/uhci-hcd/batch.c


Ignore:
Timestamp:
2011-03-22T10:07:53Z (13 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f8e4cb6
Parents:
18b3cfd (diff), b01995b (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.
Message:

Merged changes from development

File:
1 edited

Legend:

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

    r18b3cfd r62f4212  
    4040#include "batch.h"
    4141#include "transfer_list.h"
    42 #include "uhci_hc.h"
     42#include "hw_struct/transfer_descriptor.h"
    4343#include "utils/malloc32.h"
    4444
    4545#define DEFAULT_ERROR_COUNT 3
    4646
    47 static void batch_control(batch_t *instance,
     47typedef struct uhci_batch {
     48        qh_t *qh;
     49        td_t *tds;
     50        size_t packets;
     51        usb_device_keeper_t *manager;
     52} uhci_batch_t;
     53
     54static void batch_control(usb_transfer_batch_t *instance,
    4855    usb_packet_id data_stage, usb_packet_id status_stage);
    49 static void batch_data(batch_t *instance, usb_packet_id pid);
    50 static void batch_call_in(batch_t *instance);
    51 static void batch_call_out(batch_t *instance);
    52 static void batch_call_in_and_dispose(batch_t *instance);
    53 static void batch_call_out_and_dispose(batch_t *instance);
     56static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
     57static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
     58static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    5459
    5560
     
    7681 * transaction and callback.
    7782 */
    78 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
     83usb_transfer_batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    7984    usb_transfer_type_t transfer_type, size_t max_packet_size,
    80     usb_speed_t speed, char *buffer, size_t size,
     85    usb_speed_t speed, char *buffer, size_t buffer_size,
    8186    char* setup_buffer, size_t setup_size,
    8287    usbhc_iface_transfer_in_callback_t func_in,
    8388    usbhc_iface_transfer_out_callback_t func_out, void *arg,
    84     device_keeper_t *manager
     89    usb_device_keeper_t *manager
    8590    )
    8691{
     
    97102        } else (void)0
    98103
    99         batch_t *instance = malloc(sizeof(batch_t));
     104        usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
    100105        CHECK_NULL_DISPOSE_RETURN(instance,
    101106            "Failed to allocate batch instance.\n");
    102         bzero(instance, sizeof(batch_t));
    103 
    104         instance->qh = malloc32(sizeof(qh_t));
    105         CHECK_NULL_DISPOSE_RETURN(instance->qh,
     107        usb_transfer_batch_init(instance, target, transfer_type, speed, max_packet_size,
     108            buffer, NULL, buffer_size, NULL, setup_size, func_in,
     109            func_out, arg, fun, NULL);
     110
     111
     112        uhci_batch_t *data = malloc(sizeof(uhci_batch_t));
     113        CHECK_NULL_DISPOSE_RETURN(instance,
     114            "Failed to allocate batch instance.\n");
     115        bzero(data, sizeof(uhci_batch_t));
     116        data->manager = manager;
     117        instance->private_data = data;
     118
     119        data->packets = (buffer_size + max_packet_size - 1) / max_packet_size;
     120        if (transfer_type == USB_TRANSFER_CONTROL) {
     121                data->packets += 2;
     122        }
     123
     124        data->tds = malloc32(sizeof(td_t) * data->packets);
     125        CHECK_NULL_DISPOSE_RETURN(
     126            data->tds, "Failed to allocate transfer descriptors.\n");
     127        bzero(data->tds, sizeof(td_t) * data->packets);
     128
     129        data->qh = malloc32(sizeof(qh_t));
     130        CHECK_NULL_DISPOSE_RETURN(data->qh,
    106131            "Failed to allocate batch queue head.\n");
    107         qh_init(instance->qh);
    108 
    109         instance->packets = (size + max_packet_size - 1) / max_packet_size;
    110         if (transfer_type == USB_TRANSFER_CONTROL) {
    111                 instance->packets += 2;
    112         }
    113 
    114         instance->tds = malloc32(sizeof(td_t) * instance->packets);
    115         CHECK_NULL_DISPOSE_RETURN(
    116             instance->tds, "Failed to allocate transfer descriptors.\n");
    117         bzero(instance->tds, sizeof(td_t) * instance->packets);
    118 
    119         if (size > 0) {
    120                 instance->transport_buffer = malloc32(size);
     132        qh_init(data->qh);
     133        qh_set_element_td(data->qh, addr_to_phys(data->tds));
     134
     135        if (buffer_size > 0) {
     136                instance->transport_buffer = malloc32(buffer_size);
    121137                CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
    122138                    "Failed to allocate device accessible buffer.\n");
     
    130146        }
    131147
    132 
    133         link_initialize(&instance->link);
    134 
    135         instance->max_packet_size = max_packet_size;
    136         instance->target = target;
    137         instance->transfer_type = transfer_type;
    138         instance->buffer = buffer;
    139         instance->buffer_size = size;
    140         instance->setup_size = setup_size;
    141         instance->fun = fun;
    142         instance->arg = arg;
    143         instance->speed = speed;
    144         instance->manager = manager;
    145         instance->callback_out = func_out;
    146         instance->callback_in = func_in;
    147 
    148         qh_set_element_td(instance->qh, addr_to_phys(instance->tds));
    149 
    150148        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
    151149            instance, target.address, target.endpoint);
     
    153151}
    154152/*----------------------------------------------------------------------------*/
    155 /** Mark batch as failed and continue with next step.
    156  *
    157  * @param[in] instance Batch structure to use.
    158  *
    159  */
    160 void batch_abort(batch_t *instance)
    161 {
    162         assert(instance);
    163         instance->error = EIO;
    164         instance->next_step(instance);
    165 }
    166 /*----------------------------------------------------------------------------*/
    167153/** Check batch TDs for activity.
    168154 *
     
    174160 * is reached.
    175161 */
    176 bool batch_is_complete(batch_t *instance)
    177 {
    178         assert(instance);
     162bool batch_is_complete(usb_transfer_batch_t *instance)
     163{
     164        assert(instance);
     165        uhci_batch_t *data = instance->private_data;
     166        assert(data);
     167
    179168        usb_log_debug2("Batch(%p) checking %d packet(s) for completion.\n",
    180             instance, instance->packets);
     169            instance, data->packets);
    181170        instance->transfered_size = 0;
    182171        size_t i = 0;
    183         for (;i < instance->packets; ++i) {
    184                 if (td_is_active(&instance->tds[i])) {
     172        for (;i < data->packets; ++i) {
     173                if (td_is_active(&data->tds[i])) {
    185174                        return false;
    186175                }
    187176
    188                 instance->error = td_status(&instance->tds[i]);
     177                instance->error = td_status(&data->tds[i]);
    189178                if (instance->error != EOK) {
    190179                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    191                             instance, i, instance->tds[i].status);
    192                         td_print_status(&instance->tds[i]);
    193 
    194                         device_keeper_set_toggle(instance->manager,
    195                             instance->target, td_toggle(&instance->tds[i]));
     180                            instance, i, data->tds[i].status);
     181                        td_print_status(&data->tds[i]);
     182
     183                        usb_device_keeper_set_toggle(data->manager,
     184                            instance->target, instance->direction,
     185                            td_toggle(&data->tds[i]));
    196186                        if (i > 0)
    197187                                goto substract_ret;
     
    199189                }
    200190
    201                 instance->transfered_size += td_act_size(&instance->tds[i]);
    202                 if (td_is_short(&instance->tds[i]))
     191                instance->transfered_size += td_act_size(&data->tds[i]);
     192                if (td_is_short(&data->tds[i]))
    203193                        goto substract_ret;
    204194        }
     
    214204 * Uses genercir control function with pids OUT and IN.
    215205 */
    216 void batch_control_write(batch_t *instance)
     206void batch_control_write(usb_transfer_batch_t *instance)
    217207{
    218208        assert(instance);
     
    231221 * Uses generic control with pids IN and OUT.
    232222 */
    233 void batch_control_read(batch_t *instance)
     223void batch_control_read(usb_transfer_batch_t *instance)
    234224{
    235225        assert(instance);
     
    245235 * Data transaction with PID_IN.
    246236 */
    247 void batch_interrupt_in(batch_t *instance)
    248 {
    249         assert(instance);
     237void batch_interrupt_in(usb_transfer_batch_t *instance)
     238{
     239        assert(instance);
     240        instance->direction = USB_DIRECTION_IN;
    250241        batch_data(instance, USB_PID_IN);
    251242        instance->next_step = batch_call_in_and_dispose;
     
    259250 * Data transaction with PID_OUT.
    260251 */
    261 void batch_interrupt_out(batch_t *instance)
    262 {
    263         assert(instance);
     252void batch_interrupt_out(usb_transfer_batch_t *instance)
     253{
     254        assert(instance);
     255        instance->direction = USB_DIRECTION_OUT;
    264256        /* We are data out, we are supposed to provide data */
    265257        memcpy(instance->transport_buffer, instance->buffer,
     
    276268 * Data transaction with PID_IN.
    277269 */
    278 void batch_bulk_in(batch_t *instance)
     270void batch_bulk_in(usb_transfer_batch_t *instance)
    279271{
    280272        assert(instance);
    281273        batch_data(instance, USB_PID_IN);
     274        instance->direction = USB_DIRECTION_IN;
    282275        instance->next_step = batch_call_in_and_dispose;
    283276        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     
    290283 * Data transaction with PID_OUT.
    291284 */
    292 void batch_bulk_out(batch_t *instance)
    293 {
    294         assert(instance);
     285void batch_bulk_out(usb_transfer_batch_t *instance)
     286{
     287        assert(instance);
     288        instance->direction = USB_DIRECTION_OUT;
    295289        /* We are data out, we are supposed to provide data */
    296290        memcpy(instance->transport_buffer, instance->buffer,
     
    309303 * The last packet is marked with IOC flag.
    310304 */
    311 void batch_data(batch_t *instance, usb_packet_id pid)
    312 {
    313         assert(instance);
     305void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid)
     306{
     307        assert(instance);
     308        uhci_batch_t *data = instance->private_data;
     309        assert(data);
     310
    314311        const bool low_speed = instance->speed == USB_SPEED_LOW;
    315         int toggle =
    316             device_keeper_get_toggle(instance->manager, instance->target);
     312        int toggle = usb_device_keeper_get_toggle(
     313            data->manager, instance->target, instance->direction);
    317314        assert(toggle == 0 || toggle == 1);
    318315
     
    320317        size_t remain_size = instance->buffer_size;
    321318        while (remain_size > 0) {
    322                 char *data =
     319                char *trans_data =
    323320                    instance->transport_buffer + instance->buffer_size
    324321                    - remain_size;
     
    328325                    remain_size : instance->max_packet_size;
    329326
    330                 td_t *next_packet = (packet + 1 < instance->packets)
    331                     ? &instance->tds[packet + 1] : NULL;
    332 
    333                 assert(packet < instance->packets);
     327                td_t *next_packet = (packet + 1 < data->packets)
     328                    ? &data->tds[packet + 1] : NULL;
     329
     330                assert(packet < data->packets);
    334331                assert(packet_size <= remain_size);
    335332
    336333                td_init(
    337                     &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
    338                     toggle, false, low_speed, instance->target, pid, data,
     334                    &data->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
     335                    toggle, false, low_speed, instance->target, pid, trans_data,
    339336                    next_packet);
    340337
     
    344341                ++packet;
    345342        }
    346         td_set_ioc(&instance->tds[packet - 1]);
    347         device_keeper_set_toggle(instance->manager, instance->target, toggle);
     343        td_set_ioc(&data->tds[packet - 1]);
     344        usb_device_keeper_set_toggle(data->manager, instance->target,
     345            instance->direction, toggle);
    348346}
    349347/*----------------------------------------------------------------------------*/
     
    359357 * The last packet is marked with IOC.
    360358 */
    361 void batch_control(batch_t *instance,
     359void batch_control(usb_transfer_batch_t *instance,
    362360   usb_packet_id data_stage, usb_packet_id status_stage)
    363361{
    364362        assert(instance);
     363        uhci_batch_t *data = instance->private_data;
     364        assert(data);
     365        assert(data->packets >= 2);
    365366
    366367        const bool low_speed = instance->speed == USB_SPEED_LOW;
    367368        int toggle = 0;
    368369        /* setup stage */
    369         td_init(instance->tds, DEFAULT_ERROR_COUNT,
    370             instance->setup_size, toggle, false, low_speed, instance->target,
    371             USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
     370        td_init(
     371            data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, toggle, false,
     372            low_speed, instance->target, USB_PID_SETUP, instance->setup_buffer,
     373            &data->tds[1]);
    372374
    373375        /* data stage */
     
    375377        size_t remain_size = instance->buffer_size;
    376378        while (remain_size > 0) {
    377                 char *data =
     379                char *control_data =
    378380                    instance->transport_buffer + instance->buffer_size
    379381                    - remain_size;
     
    386388
    387389                td_init(
    388                     &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
     390                    &data->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
    389391                    toggle, false, low_speed, instance->target, data_stage,
    390                     data, &instance->tds[packet + 1]);
     392                    control_data, &data->tds[packet + 1]);
    391393
    392394                ++packet;
    393                 assert(packet < instance->packets);
     395                assert(packet < data->packets);
    394396                assert(packet_size <= remain_size);
    395397                remain_size -= packet_size;
     
    397399
    398400        /* status stage */
    399         assert(packet == instance->packets - 1);
    400         td_init(&instance->tds[packet], DEFAULT_ERROR_COUNT,
    401             0, 1, false, low_speed, instance->target, status_stage, NULL, NULL);
    402 
    403         td_set_ioc(&instance->tds[packet]);
     401        assert(packet == data->packets - 1);
     402
     403        td_init(
     404            &data->tds[packet], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
     405            instance->target, status_stage, NULL, NULL);
     406        td_set_ioc(&data->tds[packet]);
     407
    404408        usb_log_debug2("Control last TD status: %x.\n",
    405             instance->tds[packet].status);
    406 }
    407 /*----------------------------------------------------------------------------*/
    408 /** Prepare data, get error status and call callback in.
    409  *
    410  * @param[in] instance Batch structure to use.
    411  * Copies data from transport buffer, and calls callback with appropriate
    412  * parameters.
    413  */
    414 void batch_call_in(batch_t *instance)
    415 {
    416         assert(instance);
    417         assert(instance->callback_in);
    418 
    419         /* We are data in, we need data */
    420         memcpy(instance->buffer, instance->transport_buffer,
    421             instance->buffer_size);
    422 
    423         int err = instance->error;
    424         usb_log_debug("Batch(%p) callback IN(type:%d): %s(%d), %zu.\n",
    425             instance, instance->transfer_type, str_error(err), err,
    426             instance->transfered_size);
    427 
    428         instance->callback_in(
    429             instance->fun, err, instance->transfered_size, instance->arg);
    430 }
    431 /*----------------------------------------------------------------------------*/
    432 /** Get error status and call callback out.
    433  *
    434  * @param[in] instance Batch structure to use.
    435  */
    436 void batch_call_out(batch_t *instance)
    437 {
    438         assert(instance);
    439         assert(instance->callback_out);
    440 
    441         int err = instance->error;
    442         usb_log_debug("Batch(%p) callback OUT(type:%d): %s(%d).\n",
    443             instance, instance->transfer_type, str_error(err), err);
    444         instance->callback_out(instance->fun,
    445             err, instance->arg);
     409            data->tds[packet].status);
     410}
     411/*----------------------------------------------------------------------------*/
     412qh_t * batch_qh(usb_transfer_batch_t *instance)
     413{
     414        assert(instance);
     415        uhci_batch_t *data = instance->private_data;
     416        assert(data);
     417        return data->qh;
    446418}
    447419/*----------------------------------------------------------------------------*/
     
    450422 * @param[in] instance Batch structure to use.
    451423 */
    452 void batch_call_in_and_dispose(batch_t *instance)
    453 {
    454         assert(instance);
    455         batch_call_in(instance);
     424void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
     425{
     426        assert(instance);
     427        usb_transfer_batch_call_in(instance);
    456428        batch_dispose(instance);
    457429}
     
    461433 * @param[in] instance Batch structure to use.
    462434 */
    463 void batch_call_out_and_dispose(batch_t *instance)
    464 {
    465         assert(instance);
    466         batch_call_out(instance);
     435void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
     436{
     437        assert(instance);
     438        usb_transfer_batch_call_out(instance);
    467439        batch_dispose(instance);
    468440}
     
    472444 * @param[in] instance Batch structure to use.
    473445 */
    474 void batch_dispose(batch_t *instance)
    475 {
    476         assert(instance);
     446void batch_dispose(usb_transfer_batch_t *instance)
     447{
     448        assert(instance);
     449        uhci_batch_t *data = instance->private_data;
     450        assert(data);
    477451        usb_log_debug("Batch(%p) disposing.\n", instance);
    478452        /* free32 is NULL safe */
    479         free32(instance->tds);
    480         free32(instance->qh);
     453        free32(data->tds);
     454        free32(data->qh);
    481455        free32(instance->setup_buffer);
    482456        free32(instance->transport_buffer);
     457        free(data);
    483458        free(instance);
    484459}
Note: See TracChangeset for help on using the changeset viewer.