Ignore:
File:
1 edited

Legend:

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

    r8790650 rc9dc471  
    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                        /* Make sure TD queue is empty (one TD),
     164                         * ED should be marked as halted */
     165                        data->ed->td_tail =
     166                            (data->ed->td_head & ED_TDTAIL_PTR_MASK);
     167                        ++i;
     168                        break;
    150169                }
    151170        }
     171        data->leave_td = i;
     172        assert(data->leave_td <= data->td_count);
     173        hcd_endpoint_t *hcd_ep = hcd_endpoint_get(instance->ep);
     174        assert(hcd_ep);
     175        hcd_ep->td = data->tds[i];
     176        /* Clear possible ED HALT */
     177        data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
     178        uint32_t pa = addr_to_phys(hcd_ep->td);
     179        assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK));
     180        assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK));
     181
    152182        return true;
    153183}
    154184/*----------------------------------------------------------------------------*/
     185void batch_commit(usb_transfer_batch_t *instance)
     186{
     187        assert(instance);
     188        ohci_transfer_batch_t *data = instance->private_data;
     189        assert(data);
     190        ed_set_end_td(data->ed, data->tds[data->td_count]);
     191}
     192/*----------------------------------------------------------------------------*/
    155193void batch_control_write(usb_transfer_batch_t *instance)
    156194{
    157195        assert(instance);
    158196        /* 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;
     197        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     198        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    162199        batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
    163200        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
     
    167204{
    168205        assert(instance);
    169         instance->next_step = batch_call_in_and_dispose;
     206        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    170207        batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
    171208        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
     
    175212{
    176213        assert(instance);
    177         assert(instance->direction == USB_DIRECTION_IN);
    178         instance->next_step = batch_call_in_and_dispose;
    179         /* TODO: implement */
     214        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     215        batch_data(instance);
    180216        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    181217}
     
    184220{
    185221        assert(instance);
    186         assert(instance->direction == USB_DIRECTION_OUT);
    187222        /* 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 */
     223        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     224        instance->next_step = usb_transfer_batch_call_out_and_dispose;
     225        batch_data(instance);
    192226        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    193227}
     
    196230{
    197231        assert(instance);
    198         instance->direction = USB_DIRECTION_IN;
    199         instance->next_step = batch_call_in_and_dispose;
    200         /* TODO: implement */
     232        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     233        batch_data(instance);
    201234        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    202235}
     
    205238{
    206239        assert(instance);
    207         instance->direction = USB_DIRECTION_IN;
    208         instance->next_step = batch_call_in_and_dispose;
    209         /* TODO: implement */
     240        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     241        batch_data(instance);
    210242        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    211243}
     
    214246{
    215247        assert(instance);
    216         ohci_batch_t *data = instance->private_data;
     248        ohci_transfer_batch_t *data = instance->private_data;
    217249        assert(data);
    218250        return data->ed;
     
    223255{
    224256        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,
     257        ohci_transfer_batch_t *data = instance->private_data;
     258        assert(data);
     259        usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
    230260            data->ed->status, data->ed->td_tail, data->ed->td_head,
    231261            data->ed->next);
    232262        int toggle = 0;
    233263        /* setup stage */
    234         td_init(&data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
     264        td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
    235265                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);
     266        td_set_next(data->tds[0], data->tds[1]);
     267        usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0]->status,
     268            data->tds[0]->cbp, data->tds[0]->next, data->tds[0]->be);
    239269
    240270        /* data stage */
    241271        size_t td_current = 1;
    242272        size_t remain_size = instance->buffer_size;
    243         char *transfer_buffer = instance->transport_buffer;
     273        char *buffer = instance->data_buffer;
    244274        while (remain_size > 0) {
    245275                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     
    247277                toggle = 1 - toggle;
    248278
    249                 td_init(&data->tds[td_current], data_dir, transfer_buffer,
     279                td_init(data->tds[td_current], data_dir, buffer,
    250280                    transfer_size, toggle);
    251                 td_set_next(&data->tds[td_current], &data->tds[td_current + 1]);
     281                td_set_next(data->tds[td_current], data->tds[td_current + 1]);
    252282                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;
     283                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     284                    data->tds[td_current]->next, data->tds[td_current]->be);
     285
     286                buffer += transfer_size;
    257287                remain_size -= transfer_size;
    258                 assert(td_current < data->td_count - 2);
     288                assert(td_current < data->td_count - 1);
    259289                ++td_current;
    260290        }
    261291
    262292        /* status stage */
    263         assert(td_current == data->td_count - 2);
    264         td_init(&data->tds[td_current], status_dir, NULL, 0, 1);
     293        assert(td_current == data->td_count - 1);
     294        td_init(data->tds[td_current], status_dir, NULL, 0, 1);
     295        td_set_next(data->tds[td_current], data->tds[td_current + 1]);
    265296        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);
     297            data->tds[td_current]->status, data->tds[td_current]->cbp,
     298            data->tds[td_current]->next, data->tds[td_current]->be);
     299}
     300/*----------------------------------------------------------------------------*/
     301void batch_data(usb_transfer_batch_t *instance)
     302{
     303        assert(instance);
     304        ohci_transfer_batch_t *data = instance->private_data;
     305        assert(data);
     306        usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
     307            data->ed->status, data->ed->td_tail, data->ed->td_head,
     308            data->ed->next);
     309
     310        size_t td_current = 0;
     311        size_t remain_size = instance->buffer_size;
     312        char *buffer = instance->data_buffer;
     313        while (remain_size > 0) {
     314                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     315                    OHCI_TD_MAX_TRANSFER : remain_size;
     316
     317                td_init(data->tds[td_current], instance->ep->direction,
     318                    buffer, transfer_size, -1);
     319                td_set_next(data->tds[td_current], data->tds[td_current + 1]);
     320                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
     321                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     322                    data->tds[td_current]->next, data->tds[td_current]->be);
     323
     324                buffer += transfer_size;
     325                remain_size -= transfer_size;
     326                assert(td_current < data->td_count);
     327                ++td_current;
     328        }
    290329}
    291330/**
Note: See TracChangeset for help on using the changeset viewer.