Ignore:
File:
1 edited

Legend:

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

    r87644b4 ra963a68  
    4040#include "batch.h"
    4141#include "transfer_list.h"
    42 #include "hw_struct/transfer_descriptor.h"
     42#include "uhci_hc.h"
    4343#include "utils/malloc32.h"
    4444
    4545#define DEFAULT_ERROR_COUNT 3
    4646
    47 typedef 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 
    54 static void batch_control(usb_transfer_batch_t *instance,
     47static void batch_control(batch_t *instance,
    5548    usb_packet_id data_stage, usb_packet_id status_stage);
    56 static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
    57 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    58 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
     49static void batch_data(batch_t *instance, usb_packet_id pid);
     50static void batch_call_in(batch_t *instance);
     51static void batch_call_out(batch_t *instance);
     52static void batch_call_in_and_dispose(batch_t *instance);
     53static void batch_call_out_and_dispose(batch_t *instance);
    5954
    6055
     
    8176 * transaction and callback.
    8277 */
    83 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
     78batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    8479    usb_transfer_type_t transfer_type, size_t max_packet_size,
    85     usb_speed_t speed, char *buffer, size_t buffer_size,
     80    usb_speed_t speed, char *buffer, size_t size,
    8681    char* setup_buffer, size_t setup_size,
    8782    usbhc_iface_transfer_in_callback_t func_in,
    8883    usbhc_iface_transfer_out_callback_t func_out, void *arg,
    89     usb_device_keeper_t *manager
     84    device_keeper_t *manager
    9085    )
    9186{
     
    10297        } else (void)0
    10398
    104         usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
     99        batch_t *instance = malloc(sizeof(batch_t));
    105100        CHECK_NULL_DISPOSE_RETURN(instance,
    106101            "Failed to allocate batch instance.\n");
    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;
     102        bzero(instance, sizeof(batch_t));
     103
     104        instance->qh = malloc32(sizeof(qh_t));
     105        CHECK_NULL_DISPOSE_RETURN(instance->qh,
     106            "Failed to allocate batch queue head.\n");
     107        qh_init(instance->qh);
     108
     109        instance->packets = (size + max_packet_size - 1) / max_packet_size;
    120110        if (transfer_type == USB_TRANSFER_CONTROL) {
    121                 data->packets += 2;
    122         }
    123 
    124         data->tds = malloc32(sizeof(td_t) * data->packets);
     111                instance->packets += 2;
     112        }
     113
     114        instance->tds = malloc32(sizeof(td_t) * instance->packets);
    125115        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,
    131             "Failed to allocate batch queue head.\n");
    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);
     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);
    137121                CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
    138122                    "Failed to allocate device accessible buffer.\n");
     
    146130        }
    147131
     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
    148150        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
    149151            instance, target.address, target.endpoint);
     
    151153}
    152154/*----------------------------------------------------------------------------*/
     155/** Mark batch as failed and continue with next step.
     156 *
     157 * @param[in] instance Batch structure to use.
     158 *
     159 */
     160void batch_abort(batch_t *instance)
     161{
     162        assert(instance);
     163        instance->error = EIO;
     164        instance->next_step(instance);
     165}
     166/*----------------------------------------------------------------------------*/
    153167/** Check batch TDs for activity.
    154168 *
     
    160174 * is reached.
    161175 */
    162 bool batch_is_complete(usb_transfer_batch_t *instance)
    163 {
    164         assert(instance);
    165         uhci_batch_t *data = instance->private_data;
    166         assert(data);
    167 
     176bool batch_is_complete(batch_t *instance)
     177{
     178        assert(instance);
    168179        usb_log_debug2("Batch(%p) checking %d packet(s) for completion.\n",
    169             instance, data->packets);
     180            instance, instance->packets);
    170181        instance->transfered_size = 0;
    171182        size_t i = 0;
    172         for (;i < data->packets; ++i) {
    173                 if (td_is_active(&data->tds[i])) {
     183        for (;i < instance->packets; ++i) {
     184                if (td_is_active(&instance->tds[i])) {
    174185                        return false;
    175186                }
    176187
    177                 instance->error = td_status(&data->tds[i]);
     188                instance->error = td_status(&instance->tds[i]);
    178189                if (instance->error != EOK) {
    179190                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    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]));
     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]));
    186196                        if (i > 0)
    187197                                goto substract_ret;
     
    189199                }
    190200
    191                 instance->transfered_size += td_act_size(&data->tds[i]);
    192                 if (td_is_short(&data->tds[i]))
     201                instance->transfered_size += td_act_size(&instance->tds[i]);
     202                if (td_is_short(&instance->tds[i]))
    193203                        goto substract_ret;
    194204        }
     
    204214 * Uses genercir control function with pids OUT and IN.
    205215 */
    206 void batch_control_write(usb_transfer_batch_t *instance)
     216void batch_control_write(batch_t *instance)
    207217{
    208218        assert(instance);
     
    221231 * Uses generic control with pids IN and OUT.
    222232 */
    223 void batch_control_read(usb_transfer_batch_t *instance)
     233void batch_control_read(batch_t *instance)
    224234{
    225235        assert(instance);
     
    235245 * Data transaction with PID_IN.
    236246 */
    237 void batch_interrupt_in(usb_transfer_batch_t *instance)
    238 {
    239         assert(instance);
    240         instance->direction = USB_DIRECTION_IN;
     247void batch_interrupt_in(batch_t *instance)
     248{
     249        assert(instance);
    241250        batch_data(instance, USB_PID_IN);
    242251        instance->next_step = batch_call_in_and_dispose;
     
    250259 * Data transaction with PID_OUT.
    251260 */
    252 void batch_interrupt_out(usb_transfer_batch_t *instance)
    253 {
    254         assert(instance);
    255         instance->direction = USB_DIRECTION_OUT;
     261void batch_interrupt_out(batch_t *instance)
     262{
     263        assert(instance);
    256264        /* We are data out, we are supposed to provide data */
    257265        memcpy(instance->transport_buffer, instance->buffer,
     
    268276 * Data transaction with PID_IN.
    269277 */
    270 void batch_bulk_in(usb_transfer_batch_t *instance)
     278void batch_bulk_in(batch_t *instance)
    271279{
    272280        assert(instance);
    273281        batch_data(instance, USB_PID_IN);
    274         instance->direction = USB_DIRECTION_IN;
    275282        instance->next_step = batch_call_in_and_dispose;
    276283        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     
    283290 * Data transaction with PID_OUT.
    284291 */
    285 void batch_bulk_out(usb_transfer_batch_t *instance)
    286 {
    287         assert(instance);
    288         instance->direction = USB_DIRECTION_OUT;
     292void batch_bulk_out(batch_t *instance)
     293{
     294        assert(instance);
    289295        /* We are data out, we are supposed to provide data */
    290296        memcpy(instance->transport_buffer, instance->buffer,
     
    303309 * The last packet is marked with IOC flag.
    304310 */
    305 void 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 
     311void batch_data(batch_t *instance, usb_packet_id pid)
     312{
     313        assert(instance);
    311314        const bool low_speed = instance->speed == USB_SPEED_LOW;
    312         int toggle = usb_device_keeper_get_toggle(
    313             data->manager, instance->target, instance->direction);
     315        int toggle =
     316            device_keeper_get_toggle(instance->manager, instance->target);
    314317        assert(toggle == 0 || toggle == 1);
    315318
     
    317320        size_t remain_size = instance->buffer_size;
    318321        while (remain_size > 0) {
    319                 char *trans_data =
     322                char *data =
    320323                    instance->transport_buffer + instance->buffer_size
    321324                    - remain_size;
     
    325328                    remain_size : instance->max_packet_size;
    326329
    327                 td_t *next_packet = (packet + 1 < data->packets)
    328                     ? &data->tds[packet + 1] : NULL;
    329 
    330                 assert(packet < data->packets);
     330                td_t *next_packet = (packet + 1 < instance->packets)
     331                    ? &instance->tds[packet + 1] : NULL;
     332
     333                assert(packet < instance->packets);
    331334                assert(packet_size <= remain_size);
    332335
    333336                td_init(
    334                     &data->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
    335                     toggle, false, low_speed, instance->target, pid, trans_data,
     337                    &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
     338                    toggle, false, low_speed, instance->target, pid, data,
    336339                    next_packet);
    337340
     
    341344                ++packet;
    342345        }
    343         td_set_ioc(&data->tds[packet - 1]);
    344         usb_device_keeper_set_toggle(data->manager, instance->target,
    345             instance->direction, toggle);
     346        td_set_ioc(&instance->tds[packet - 1]);
     347        device_keeper_set_toggle(instance->manager, instance->target, toggle);
    346348}
    347349/*----------------------------------------------------------------------------*/
     
    357359 * The last packet is marked with IOC.
    358360 */
    359 void batch_control(usb_transfer_batch_t *instance,
     361void batch_control(batch_t *instance,
    360362   usb_packet_id data_stage, usb_packet_id status_stage)
    361363{
    362364        assert(instance);
    363         uhci_batch_t *data = instance->private_data;
    364         assert(data);
    365         assert(data->packets >= 2);
    366365
    367366        const bool low_speed = instance->speed == USB_SPEED_LOW;
    368367        int toggle = 0;
    369368        /* setup stage */
    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]);
     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]);
    374372
    375373        /* data stage */
     
    377375        size_t remain_size = instance->buffer_size;
    378376        while (remain_size > 0) {
    379                 char *control_data =
     377                char *data =
    380378                    instance->transport_buffer + instance->buffer_size
    381379                    - remain_size;
     
    388386
    389387                td_init(
    390                     &data->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
     388                    &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
    391389                    toggle, false, low_speed, instance->target, data_stage,
    392                     control_data, &data->tds[packet + 1]);
     390                    data, &instance->tds[packet + 1]);
    393391
    394392                ++packet;
    395                 assert(packet < data->packets);
     393                assert(packet < instance->packets);
    396394                assert(packet_size <= remain_size);
    397395                remain_size -= packet_size;
     
    399397
    400398        /* status stage */
    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 
     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]);
    408404        usb_log_debug2("Control last TD status: %x.\n",
    409             data->tds[packet].status);
    410 }
    411 /*----------------------------------------------------------------------------*/
    412 qh_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;
     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 */
     414void 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 */
     436void 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);
    418446}
    419447/*----------------------------------------------------------------------------*/
     
    422450 * @param[in] instance Batch structure to use.
    423451 */
    424 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    425 {
    426         assert(instance);
    427         usb_transfer_batch_call_in(instance);
     452void batch_call_in_and_dispose(batch_t *instance)
     453{
     454        assert(instance);
     455        batch_call_in(instance);
    428456        batch_dispose(instance);
    429457}
     
    433461 * @param[in] instance Batch structure to use.
    434462 */
    435 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    436 {
    437         assert(instance);
    438         usb_transfer_batch_call_out(instance);
     463void batch_call_out_and_dispose(batch_t *instance)
     464{
     465        assert(instance);
     466        batch_call_out(instance);
    439467        batch_dispose(instance);
    440468}
     
    444472 * @param[in] instance Batch structure to use.
    445473 */
    446 void batch_dispose(usb_transfer_batch_t *instance)
    447 {
    448         assert(instance);
    449         uhci_batch_t *data = instance->private_data;
    450         assert(data);
     474void batch_dispose(batch_t *instance)
     475{
     476        assert(instance);
    451477        usb_log_debug("Batch(%p) disposing.\n", instance);
    452478        /* free32 is NULL safe */
    453         free32(data->tds);
    454         free32(data->qh);
     479        free32(instance->tds);
     480        free32(instance->qh);
    455481        free32(instance->setup_buffer);
    456482        free32(instance->transport_buffer);
    457         free(data);
    458483        free(instance);
    459484}
Note: See TracChangeset for help on using the changeset viewer.