Ignore:
File:
1 edited

Legend:

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

    raa9ccf7 rd6522dd  
    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);
    5373static void batch_data(usb_transfer_batch_t *instance);
    54 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    55 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    56 
    57 #define DEFAULT_ERROR_COUNT 3
     74/*----------------------------------------------------------------------------*/
    5875usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
    5976    char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
     
    6582                usb_log_error(message); \
    6683                if (instance) { \
    67                         batch_dispose(instance); \
     84                        usb_transfer_batch_dispose(instance); \
    6885                } \
    6986                return NULL; \
     
    7390        CHECK_NULL_DISPOSE_RETURN(instance,
    7491            "Failed to allocate batch instance.\n");
    75         usb_target_t target =
    76             { .address = ep->address, .endpoint = ep->endpoint };
    77         usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed,
    78             ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
    79             func_in, func_out, arg, fun, ep, NULL);
    80 
    81         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);
    82100        CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
    83         bzero(data, sizeof(ohci_batch_t));
    84101        instance->private_data = data;
    85102
    86         /* we needs + 1 transfer descriptor as the last one won't be executed */
    87         data->td_count = 1 +
     103        data->td_count =
    88104            ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
    89105        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     
    91107        }
    92108
    93         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);
    94111        CHECK_NULL_DISPOSE_RETURN(data->tds,
    95112            "Failed to allocate transfer descriptors.\n");
    96         bzero(data->tds, sizeof(td_t) * data->td_count);
    97 
    98         data->ed = malloc32(sizeof(ed_t));
    99         CHECK_NULL_DISPOSE_RETURN(data->ed,
    100             "Failed to allocate endpoint descriptor.\n");
    101 
    102         if (buffer_size > 0) {
    103                 instance->transport_buffer = malloc32(buffer_size);
    104                 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,
    105128                    "Failed to allocate device accessible buffer.\n");
    106         }
    107 
    108         if (setup_size > 0) {
    109                 instance->setup_buffer = malloc32(setup_size);
    110                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    111                     "Failed to allocate device accessible setup buffer.\n");
     129                instance->setup_buffer = data->device_buffer;
     130                instance->data_buffer = data->device_buffer + setup_size;
    112131                memcpy(instance->setup_buffer, setup_buffer, setup_size);
    113132        }
     
    116135}
    117136/*----------------------------------------------------------------------------*/
    118 void batch_dispose(usb_transfer_batch_t *instance)
    119 {
    120         assert(instance);
    121         ohci_batch_t *data = instance->private_data;
    122         assert(data);
    123         free32(data->ed);
    124         free32(data->tds);
    125         free32(instance->setup_buffer);
    126         free32(instance->transport_buffer);
    127         free(data);
    128         free(instance);
    129 }
    130 /*----------------------------------------------------------------------------*/
    131137bool batch_is_complete(usb_transfer_batch_t *instance)
    132138{
    133139        assert(instance);
    134         ohci_batch_t *data = instance->private_data;
    135         assert(data);
    136         size_t tds = data->td_count - 1;
     140        ohci_transfer_batch_t *data = instance->private_data;
     141        assert(data);
     142        size_t tds = data->td_count;
    137143        usb_log_debug("Batch(%p) checking %d td(s) for completion.\n",
    138144            instance, tds);
     
    142148        size_t i = 0;
    143149        for (; i < tds; ++i) {
     150                assert(data->tds[i] != NULL);
    144151                usb_log_debug("TD %d: %x:%x:%x:%x.\n", i,
    145                     data->tds[i].status, data->tds[i].cbp, data->tds[i].next,
    146                     data->tds[i].be);
    147                 if (!td_is_finished(&data->tds[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])) {
    148155                        return false;
    149156                }
    150                 instance->error = td_error(&data->tds[i]);
     157                instance->error = td_error(data->tds[i]);
    151158                /* FIXME: calculate real transfered size */
    152159                instance->transfered_size = instance->buffer_size;
    153160                if (instance->error != EOK) {
    154161                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    155                             instance, i, data->tds[i].status);
    156                         return true;
    157 //                      endpoint_toggle_set(instance->ep,
     162                            instance, i, data->tds[i]->status);
     163                        break;
    158164                }
    159165        }
     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
    160172        return true;
    161173}
    162174/*----------------------------------------------------------------------------*/
     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/*----------------------------------------------------------------------------*/
    163183void batch_control_write(usb_transfer_batch_t *instance)
    164184{
    165185        assert(instance);
    166186        /* We are data out, we are supposed to provide data */
    167         memcpy(instance->transport_buffer, instance->buffer,
    168             instance->buffer_size);
    169         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;
    170189        batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
    171190        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
     
    175194{
    176195        assert(instance);
    177         instance->next_step = batch_call_in_and_dispose;
     196        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    178197        batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
    179198        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
     
    183202{
    184203        assert(instance);
    185         assert(instance->direction == USB_DIRECTION_IN);
    186         instance->next_step = batch_call_in_and_dispose;
     204        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    187205        batch_data(instance);
    188206        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
     
    192210{
    193211        assert(instance);
    194         assert(instance->direction == USB_DIRECTION_OUT);
    195212        /* We are data out, we are supposed to provide data */
    196         memcpy(instance->transport_buffer, instance->buffer,
    197             instance->buffer_size);
    198         instance->next_step = batch_call_out_and_dispose;
     213        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     214        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    199215        batch_data(instance);
    200216        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
     
    204220{
    205221        assert(instance);
    206         instance->direction = USB_DIRECTION_IN;
    207         instance->next_step = batch_call_in_and_dispose;
     222        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    208223        batch_data(instance);
    209224        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     
    213228{
    214229        assert(instance);
    215         instance->direction = USB_DIRECTION_IN;
    216         instance->next_step = batch_call_in_and_dispose;
     230        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    217231        batch_data(instance);
    218232        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     
    222236{
    223237        assert(instance);
    224         ohci_batch_t *data = instance->private_data;
     238        ohci_transfer_batch_t *data = instance->private_data;
    225239        assert(data);
    226240        return data->ed;
     
    231245{
    232246        assert(instance);
    233         ohci_batch_t *data = instance->private_data;
    234         assert(data);
    235         ed_init(data->ed, instance->ep);
    236         ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]);
    237         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,
    238250            data->ed->status, data->ed->td_tail, data->ed->td_head,
    239251            data->ed->next);
    240252        int toggle = 0;
    241253        /* setup stage */
    242         td_init(&data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
     254        td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
    243255                instance->setup_size, toggle);
    244         td_set_next(&data->tds[0], &data->tds[1]);
    245         usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0].status,
    246             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);
    247259
    248260        /* data stage */
    249261        size_t td_current = 1;
    250262        size_t remain_size = instance->buffer_size;
    251         char *transfer_buffer = instance->transport_buffer;
     263        char *buffer = instance->data_buffer;
    252264        while (remain_size > 0) {
    253265                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     
    255267                toggle = 1 - toggle;
    256268
    257                 td_init(&data->tds[td_current], data_dir, transfer_buffer,
     269                td_init(data->tds[td_current], data_dir, buffer,
    258270                    transfer_size, toggle);
    259                 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]);
    260272                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
    261                     data->tds[td_current].status, data->tds[td_current].cbp,
    262                     data->tds[td_current].next, data->tds[td_current].be);
    263 
    264                 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;
    265277                remain_size -= transfer_size;
    266                 assert(td_current < data->td_count - 2);
     278                assert(td_current < data->td_count - 1);
    267279                ++td_current;
    268280        }
    269281
    270282        /* status stage */
    271         assert(td_current == data->td_count - 2);
    272         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]);
    273286        usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n",
    274             data->tds[td_current].status, data->tds[td_current].cbp,
    275             data->tds[td_current].next, data->tds[td_current].be);
     287            data->tds[td_current]->status, data->tds[td_current]->cbp,
     288            data->tds[td_current]->next, data->tds[td_current]->be);
    276289}
    277290/*----------------------------------------------------------------------------*/
     
    279292{
    280293        assert(instance);
    281         ohci_batch_t *data = instance->private_data;
    282         assert(data);
    283         ed_init(data->ed, instance->ep);
    284         ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]);
    285         usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed,
     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,
    286297            data->ed->status, data->ed->td_tail, data->ed->td_head,
    287298            data->ed->next);
    288299
    289         /* data stage */
    290300        size_t td_current = 0;
    291301        size_t remain_size = instance->buffer_size;
    292         char *transfer_buffer = instance->transport_buffer;
     302        char *buffer = instance->data_buffer;
    293303        while (remain_size > 0) {
    294304                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
    295305                    OHCI_TD_MAX_TRANSFER : remain_size;
    296306
    297                 td_init(&data->tds[td_current], instance->ep->direction,
    298                     transfer_buffer, transfer_size, -1);
    299                 td_set_next(&data->tds[td_current], &data->tds[td_current + 1]);
     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]);
    300310                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
    301                     data->tds[td_current].status, data->tds[td_current].cbp,
    302                     data->tds[td_current].next, data->tds[td_current].be);
    303 
    304                 transfer_buffer += transfer_size;
     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;
    305315                remain_size -= transfer_size;
    306316                assert(td_current < data->td_count);
     
    308318        }
    309319}
    310 /*----------------------------------------------------------------------------*/
    311 /** Helper function calls callback and correctly disposes of batch structure.
    312  *
    313  * @param[in] instance Batch structure to use.
    314  */
    315 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    316 {
    317         assert(instance);
    318         usb_transfer_batch_call_in(instance);
    319         batch_dispose(instance);
    320 }
    321 /*----------------------------------------------------------------------------*/
    322 /** Helper function calls callback and correctly disposes of batch structure.
    323  *
    324  * @param[in] instance Batch structure to use.
    325  */
    326 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    327 {
    328         assert(instance);
    329         usb_transfer_batch_call_out(instance);
    330         batch_dispose(instance);
    331 }
    332320/**
    333321 * @}
Note: See TracChangeset for help on using the changeset viewer.