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


Ignore:
Timestamp:
2011-04-29T13:43:01Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a81a1d09
Parents:
380e0364 (diff), f19f1b7 (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

    r380e0364 re1dbcbc  
    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 %zu 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;
     149        instance->transfered_size = instance->buffer_size;
    139150        for (; i < tds; ++i) {
    140                 if (!td_is_finished(&data->tds[i]))
     151                assert(data->tds[i] != NULL);
     152                usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i,
     153                    data->tds[i]->status, data->tds[i]->cbp, data->tds[i]->next,
     154                    data->tds[i]->be);
     155                if (!td_is_finished(data->tds[i])) {
    141156                        return false;
    142                 instance->error = td_error(&data->tds[i]);
    143                 /* FIXME: calculate real transfered size */
    144                 instance->transfered_size = instance->buffer_size;
     157                }
     158                instance->error = td_error(data->tds[i]);
    145159                if (instance->error != EOK) {
    146                         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,
     160                        usb_log_debug("Batch(%p) found error TD(%zu):%x.\n",
     161                            instance, i, data->tds[i]->status);
     162                        /* Make sure TD queue is empty (one TD),
     163                         * ED should be marked as halted */
     164                        data->ed->td_tail =
     165                            (data->ed->td_head & ED_TDTAIL_PTR_MASK);
     166                        ++i;
     167                        break;
    150168                }
    151169        }
     170        data->leave_td = i;
     171        assert(data->leave_td <= data->td_count);
     172        hcd_endpoint_t *hcd_ep = hcd_endpoint_get(instance->ep);
     173        assert(hcd_ep);
     174        hcd_ep->td = data->tds[i];
     175        if (i > 0)
     176                instance->transfered_size -= td_remain_size(data->tds[i - 1]);
     177
     178        /* Clear possible ED HALT */
     179        data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
     180        uint32_t pa = addr_to_phys(hcd_ep->td);
     181        assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK));
     182        assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK));
     183
    152184        return true;
    153185}
    154186/*----------------------------------------------------------------------------*/
     187void batch_commit(usb_transfer_batch_t *instance)
     188{
     189        assert(instance);
     190        ohci_transfer_batch_t *data = instance->private_data;
     191        assert(data);
     192        ed_set_end_td(data->ed, data->tds[data->td_count]);
     193}
     194/*----------------------------------------------------------------------------*/
    155195void batch_control_write(usb_transfer_batch_t *instance)
    156196{
    157197        assert(instance);
    158198        /* 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;
     199        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     200        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    162201        batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
    163202        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
     
    167206{
    168207        assert(instance);
    169         instance->next_step = batch_call_in_and_dispose;
     208        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    170209        batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
    171210        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
     
    175214{
    176215        assert(instance);
    177         assert(instance->direction == USB_DIRECTION_IN);
    178         instance->next_step = batch_call_in_and_dispose;
    179         /* TODO: implement */
     216        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     217        batch_data(instance);
    180218        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    181219}
     
    184222{
    185223        assert(instance);
    186         assert(instance->direction == USB_DIRECTION_OUT);
    187224        /* 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 */
     225        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     226        instance->next_step = usb_transfer_batch_call_out_and_dispose;
     227        batch_data(instance);
    192228        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    193229}
     
    196232{
    197233        assert(instance);
    198         instance->direction = USB_DIRECTION_IN;
    199         instance->next_step = batch_call_in_and_dispose;
    200         /* TODO: implement */
     234        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     235        batch_data(instance);
    201236        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    202237}
     
    205240{
    206241        assert(instance);
    207         instance->direction = USB_DIRECTION_IN;
    208         instance->next_step = batch_call_in_and_dispose;
    209         /* TODO: implement */
    210         usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     242        /* We are data out, we are supposed to provide data */
     243        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     244        instance->next_step = usb_transfer_batch_call_out_and_dispose;
     245        batch_data(instance);
     246        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
    211247}
    212248/*----------------------------------------------------------------------------*/
     
    214250{
    215251        assert(instance);
    216         ohci_batch_t *data = instance->private_data;
     252        ohci_transfer_batch_t *data = instance->private_data;
    217253        assert(data);
    218254        return data->ed;
     
    223259{
    224260        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,
     261        ohci_transfer_batch_t *data = instance->private_data;
     262        assert(data);
     263        usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
    230264            data->ed->status, data->ed->td_tail, data->ed->td_head,
    231265            data->ed->next);
    232266        int toggle = 0;
    233267        /* setup stage */
    234         td_init(&data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
     268        td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
    235269                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);
     270        td_set_next(data->tds[0], data->tds[1]);
     271        usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0]->status,
     272            data->tds[0]->cbp, data->tds[0]->next, data->tds[0]->be);
    239273
    240274        /* data stage */
    241275        size_t td_current = 1;
    242276        size_t remain_size = instance->buffer_size;
    243         char *transfer_buffer = instance->transport_buffer;
     277        char *buffer = instance->data_buffer;
    244278        while (remain_size > 0) {
    245279                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     
    247281                toggle = 1 - toggle;
    248282
    249                 td_init(&data->tds[td_current], data_dir, transfer_buffer,
     283                td_init(data->tds[td_current], data_dir, buffer,
    250284                    transfer_size, toggle);
    251                 td_set_next(&data->tds[td_current], &data->tds[td_current + 1]);
     285                td_set_next(data->tds[td_current], data->tds[td_current + 1]);
    252286                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;
     287                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     288                    data->tds[td_current]->next, data->tds[td_current]->be);
     289
     290                buffer += transfer_size;
    257291                remain_size -= transfer_size;
    258                 assert(td_current < data->td_count - 2);
     292                assert(td_current < data->td_count - 1);
    259293                ++td_current;
    260294        }
    261295
    262296        /* status stage */
    263         assert(td_current == data->td_count - 2);
    264         td_init(&data->tds[td_current], status_dir, NULL, 0, 1);
     297        assert(td_current == data->td_count - 1);
     298        td_init(data->tds[td_current], status_dir, NULL, 0, 1);
     299        td_set_next(data->tds[td_current], data->tds[td_current + 1]);
    265300        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);
     301            data->tds[td_current]->status, data->tds[td_current]->cbp,
     302            data->tds[td_current]->next, data->tds[td_current]->be);
     303}
     304/*----------------------------------------------------------------------------*/
     305void batch_data(usb_transfer_batch_t *instance)
     306{
     307        assert(instance);
     308        ohci_transfer_batch_t *data = instance->private_data;
     309        assert(data);
     310        usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
     311            data->ed->status, data->ed->td_tail, data->ed->td_head,
     312            data->ed->next);
     313
     314        size_t td_current = 0;
     315        size_t remain_size = instance->buffer_size;
     316        char *buffer = instance->data_buffer;
     317        while (remain_size > 0) {
     318                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     319                    OHCI_TD_MAX_TRANSFER : remain_size;
     320
     321                td_init(data->tds[td_current], instance->ep->direction,
     322                    buffer, transfer_size, -1);
     323                td_set_next(data->tds[td_current], data->tds[td_current + 1]);
     324                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
     325                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     326                    data->tds[td_current]->next, data->tds[td_current]->be);
     327
     328                buffer += transfer_size;
     329                remain_size -= transfer_size;
     330                assert(td_current < data->td_count);
     331                ++td_current;
     332        }
    290333}
    291334/**
Note: See TracChangeset for help on using the changeset viewer.