Changeset d8b275d in mainline for uspace/drv/ohci/batch.c


Ignore:
Timestamp:
2011-04-14T08:24:29Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5e07e2b5
Parents:
3f2af64 (diff), 34e8bab (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:

Merge development/ changes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/ohci/batch.c

    r3f2af64 rd8b275d  
    3939
    4040#include "batch.h"
     41#include "hcd_endpoint.h"
    4142#include "utils/malloc32.h"
    4243#include "hw_struct/endpoint_descriptor.h"
    4344#include "hw_struct/transfer_descriptor.h"
    4445
    45 typedef struct ohci_batch {
     46typedef struct ohci_transfer_batch {
    4647        ed_t *ed;
    47         td_t *tds;
     48        td_t **tds;
    4849        size_t td_count;
    49 } ohci_batch_t;
    50 
     50        size_t leave_td;
     51        char *device_buffer;
     52} ohci_transfer_batch_t;
     53
     54static void ohci_transfer_batch_dispose(void *ohci_batch)
     55{
     56        ohci_transfer_batch_t *instance = ohci_batch;
     57        if (!instance)
     58                return;
     59        free32(instance->device_buffer);
     60        unsigned i = 0;
     61        if (instance->tds) {
     62                for (; i< instance->td_count; ++i) {
     63                        if (i != instance->leave_td)
     64                                free32(instance->tds[i]);
     65                }
     66                free(instance->tds);
     67        }
     68        free(instance);
     69}
     70/*----------------------------------------------------------------------------*/
    5171static void batch_control(usb_transfer_batch_t *instance,
    5272    usb_direction_t data_dir, usb_direction_t status_dir);
    53 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    54 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    55 
    56 #define DEFAULT_ERROR_COUNT 3
     73static void batch_data(usb_transfer_batch_t *instance);
     74/*----------------------------------------------------------------------------*/
    5775usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
    5876    char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
     
    6482                usb_log_error(message); \
    6583                if (instance) { \
    66                         batch_dispose(instance); \
     84                        usb_transfer_batch_dispose(instance); \
    6785                } \
    6886                return NULL; \
     
    7290        CHECK_NULL_DISPOSE_RETURN(instance,
    7391            "Failed to allocate batch instance.\n");
    74         usb_target_t target =
    75             { .address = ep->address, .endpoint = ep->endpoint };
    76         usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed,
    77             ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
    78             func_in, func_out, arg, fun, ep, NULL);
    79 
    80         ohci_batch_t *data = malloc(sizeof(ohci_batch_t));
     92        usb_transfer_batch_init(instance, ep, buffer, NULL, buffer_size,
     93            NULL, setup_size, func_in, func_out, arg, fun, NULL,
     94            ohci_transfer_batch_dispose);
     95
     96        hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
     97        assert(hcd_ep);
     98
     99        ohci_transfer_batch_t *data = calloc(sizeof(ohci_transfer_batch_t), 1);
    81100        CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
    82         bzero(data, sizeof(ohci_batch_t));
    83101        instance->private_data = data;
    84102
    85         /* we needs + 1 transfer descriptor as the last one won't be executed */
    86         data->td_count = 1 +
     103        data->td_count =
    87104            ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
    88105        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     
    90107        }
    91108
    92         data->tds = malloc32(sizeof(td_t) * data->td_count);
     109        /* we need one extra place for td that is currently assigned to hcd_ep*/
     110        data->tds = calloc(sizeof(td_t*), data->td_count + 1);
    93111        CHECK_NULL_DISPOSE_RETURN(data->tds,
    94112            "Failed to allocate transfer descriptors.\n");
    95         bzero(data->tds, sizeof(td_t) * data->td_count);
    96 
    97         data->ed = malloc32(sizeof(ed_t));
    98         CHECK_NULL_DISPOSE_RETURN(data->ed,
    99             "Failed to allocate endpoint descriptor.\n");
    100 
    101         if (buffer_size > 0) {
    102                 instance->transport_buffer = malloc32(buffer_size);
    103                 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
     113
     114        data->tds[0] = hcd_ep->td;
     115        data->leave_td = 0;
     116        unsigned i = 1;
     117        for (; i <= data->td_count; ++i) {
     118                data->tds[i] = malloc32(sizeof(td_t));
     119                CHECK_NULL_DISPOSE_RETURN(data->tds[i],
     120                    "Failed to allocate TD %d.\n", i );
     121        }
     122
     123        data->ed = hcd_ep->ed;
     124
     125        if (setup_size + buffer_size > 0) {
     126                data->device_buffer = malloc32(setup_size + buffer_size);
     127                CHECK_NULL_DISPOSE_RETURN(data->device_buffer,
    104128                    "Failed to allocate device accessible buffer.\n");
    105         }
    106 
    107         if (setup_size > 0) {
    108                 instance->setup_buffer = malloc32(setup_size);
    109                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    110                     "Failed to allocate device accessible setup buffer.\n");
     129                instance->setup_buffer = data->device_buffer;
     130                instance->data_buffer = data->device_buffer + setup_size;
    111131                memcpy(instance->setup_buffer, setup_buffer, setup_size);
    112132        }
     
    115135}
    116136/*----------------------------------------------------------------------------*/
    117 void batch_dispose(usb_transfer_batch_t *instance)
    118 {
    119         assert(instance);
    120         ohci_batch_t *data = instance->private_data;
    121         assert(data);
    122         free32(data->ed);
    123         free32(data->tds);
    124         free32(instance->setup_buffer);
    125         free32(instance->transport_buffer);
    126         free(data);
    127         free(instance);
    128 }
    129 /*----------------------------------------------------------------------------*/
    130137bool batch_is_complete(usb_transfer_batch_t *instance)
    131138{
    132139        assert(instance);
    133         ohci_batch_t *data = instance->private_data;
    134         assert(data);
    135         size_t tds = data->td_count - 1;
    136         usb_log_debug2("Batch(%p) checking %d td(s) for completion.\n",
     140        ohci_transfer_batch_t *data = instance->private_data;
     141        assert(data);
     142        size_t tds = data->td_count;
     143        usb_log_debug("Batch(%p) checking %d td(s) for completion.\n",
    137144            instance, tds);
     145        usb_log_debug("ED: %x:%x:%x:%x.\n",
     146            data->ed->status, data->ed->td_head, data->ed->td_tail,
     147            data->ed->next);
    138148        size_t i = 0;
    139149        for (; i < tds; ++i) {
    140                 if (!td_is_finished(&data->tds[i]))
     150                assert(data->tds[i] != NULL);
     151                usb_log_debug("TD %d: %x:%x:%x:%x.\n", i,
     152                    data->tds[i]->status, data->tds[i]->cbp, data->tds[i]->next,
     153                    data->tds[i]->be);
     154                if (!td_is_finished(data->tds[i])) {
    141155                        return false;
    142                 instance->error = td_error(&data->tds[i]);
     156                }
     157                instance->error = td_error(data->tds[i]);
    143158                /* FIXME: calculate real transfered size */
    144159                instance->transfered_size = instance->buffer_size;
    145160                if (instance->error != EOK) {
    146161                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    147                             instance, i, data->tds[i].status);
    148                         return true;
    149 //                      endpoint_toggle_set(instance->ep,
     162                            instance, i, data->tds[i]->status);
     163                        break;
    150164                }
    151165        }
     166        data->leave_td = i;
     167        assert(data->leave_td <= data->td_count);
     168        hcd_endpoint_t *hcd_ep = hcd_endpoint_get(instance->ep);
     169        assert(hcd_ep);
     170        hcd_ep->td = data->tds[i];
     171
    152172        return true;
    153173}
    154174/*----------------------------------------------------------------------------*/
     175void batch_commit(usb_transfer_batch_t *instance)
     176{
     177        assert(instance);
     178        ohci_transfer_batch_t *data = instance->private_data;
     179        assert(data);
     180        ed_set_end_td(data->ed, data->tds[data->td_count]);
     181}
     182/*----------------------------------------------------------------------------*/
    155183void batch_control_write(usb_transfer_batch_t *instance)
    156184{
    157185        assert(instance);
    158186        /* We are data out, we are supposed to provide data */
    159         memcpy(instance->transport_buffer, instance->buffer,
    160             instance->buffer_size);
    161         instance->next_step = batch_call_out_and_dispose;
     187        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     188        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    162189        batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
    163190        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
     
    167194{
    168195        assert(instance);
    169         instance->next_step = batch_call_in_and_dispose;
     196        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    170197        batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
    171198        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
     
    175202{
    176203        assert(instance);
    177         assert(instance->direction == USB_DIRECTION_IN);
    178         instance->next_step = batch_call_in_and_dispose;
    179         /* TODO: implement */
     204        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     205        batch_data(instance);
    180206        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    181207}
     
    184210{
    185211        assert(instance);
    186         assert(instance->direction == USB_DIRECTION_OUT);
    187212        /* We are data out, we are supposed to provide data */
    188         memcpy(instance->transport_buffer, instance->buffer,
    189             instance->buffer_size);
    190         instance->next_step = batch_call_out_and_dispose;
    191         /* TODO: implement */
     213        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     214        instance->next_step = usb_transfer_batch_call_out_and_dispose;
     215        batch_data(instance);
    192216        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    193217}
     
    196220{
    197221        assert(instance);
    198         instance->direction = USB_DIRECTION_IN;
    199         instance->next_step = batch_call_in_and_dispose;
    200         /* TODO: implement */
     222        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     223        batch_data(instance);
    201224        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    202225}
     
    205228{
    206229        assert(instance);
    207         instance->direction = USB_DIRECTION_IN;
    208         instance->next_step = batch_call_in_and_dispose;
    209         /* TODO: implement */
     230        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     231        batch_data(instance);
    210232        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    211233}
     
    214236{
    215237        assert(instance);
    216         ohci_batch_t *data = instance->private_data;
     238        ohci_transfer_batch_t *data = instance->private_data;
    217239        assert(data);
    218240        return data->ed;
     
    223245{
    224246        assert(instance);
    225         ohci_batch_t *data = instance->private_data;
    226         assert(data);
    227         ed_init(data->ed, instance->ep);
    228         ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]);
    229         usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed,
     247        ohci_transfer_batch_t *data = instance->private_data;
     248        assert(data);
     249        usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
    230250            data->ed->status, data->ed->td_tail, data->ed->td_head,
    231251            data->ed->next);
    232252        int toggle = 0;
    233253        /* setup stage */
    234         td_init(&data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
     254        td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
    235255                instance->setup_size, toggle);
    236         td_set_next(&data->tds[0], &data->tds[1]);
    237         usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0].status,
    238             data->tds[0].cbp, data->tds[0].next, data->tds[0].be);
     256        td_set_next(data->tds[0], data->tds[1]);
     257        usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0]->status,
     258            data->tds[0]->cbp, data->tds[0]->next, data->tds[0]->be);
    239259
    240260        /* data stage */
    241261        size_t td_current = 1;
    242262        size_t remain_size = instance->buffer_size;
    243         char *transfer_buffer = instance->transport_buffer;
     263        char *buffer = instance->data_buffer;
    244264        while (remain_size > 0) {
    245265                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     
    247267                toggle = 1 - toggle;
    248268
    249                 td_init(&data->tds[td_current], data_dir, transfer_buffer,
     269                td_init(data->tds[td_current], data_dir, buffer,
    250270                    transfer_size, toggle);
    251                 td_set_next(&data->tds[td_current], &data->tds[td_current + 1]);
     271                td_set_next(data->tds[td_current], data->tds[td_current + 1]);
    252272                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
    253                     data->tds[td_current].status, data->tds[td_current].cbp,
    254                     data->tds[td_current].next, data->tds[td_current].be);
    255 
    256                 transfer_buffer += transfer_size;
     273                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     274                    data->tds[td_current]->next, data->tds[td_current]->be);
     275
     276                buffer += transfer_size;
    257277                remain_size -= transfer_size;
    258                 assert(td_current < data->td_count - 2);
     278                assert(td_current < data->td_count - 1);
    259279                ++td_current;
    260280        }
    261281
    262282        /* status stage */
    263         assert(td_current == data->td_count - 2);
    264         td_init(&data->tds[td_current], status_dir, NULL, 0, 1);
     283        assert(td_current == data->td_count - 1);
     284        td_init(data->tds[td_current], status_dir, NULL, 0, 1);
     285        td_set_next(data->tds[td_current], data->tds[td_current + 1]);
    265286        usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n",
    266             data->tds[td_current].status, data->tds[td_current].cbp,
    267             data->tds[td_current].next, data->tds[td_current].be);
    268 }
    269 /*----------------------------------------------------------------------------*/
    270 /** Helper function calls callback and correctly disposes of batch structure.
    271  *
    272  * @param[in] instance Batch structure to use.
    273  */
    274 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    275 {
    276         assert(instance);
    277         usb_transfer_batch_call_in(instance);
    278         batch_dispose(instance);
    279 }
    280 /*----------------------------------------------------------------------------*/
    281 /** Helper function calls callback and correctly disposes of batch structure.
    282  *
    283  * @param[in] instance Batch structure to use.
    284  */
    285 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    286 {
    287         assert(instance);
    288         usb_transfer_batch_call_out(instance);
    289         batch_dispose(instance);
     287            data->tds[td_current]->status, data->tds[td_current]->cbp,
     288            data->tds[td_current]->next, data->tds[td_current]->be);
     289}
     290/*----------------------------------------------------------------------------*/
     291void batch_data(usb_transfer_batch_t *instance)
     292{
     293        assert(instance);
     294        ohci_transfer_batch_t *data = instance->private_data;
     295        assert(data);
     296        usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
     297            data->ed->status, data->ed->td_tail, data->ed->td_head,
     298            data->ed->next);
     299
     300        size_t td_current = 0;
     301        size_t remain_size = instance->buffer_size;
     302        char *buffer = instance->data_buffer;
     303        while (remain_size > 0) {
     304                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     305                    OHCI_TD_MAX_TRANSFER : remain_size;
     306
     307                td_init(data->tds[td_current], instance->ep->direction,
     308                    buffer, transfer_size, -1);
     309                td_set_next(data->tds[td_current], data->tds[td_current + 1]);
     310                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
     311                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     312                    data->tds[td_current]->next, data->tds[td_current]->be);
     313
     314                buffer += transfer_size;
     315                remain_size -= transfer_size;
     316                assert(td_current < data->td_count);
     317                ++td_current;
     318        }
    290319}
    291320/**
Note: See TracChangeset for help on using the changeset viewer.