Ignore:
File:
1 edited

Legend:

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

    rf567bcf rf1be95c8  
    4040#include "batch.h"
    4141#include "utils/malloc32.h"
    42 
     42#include "hw_struct/endpoint_descriptor.h"
     43#include "hw_struct/transfer_descriptor.h"
     44
     45typedef struct ohci_batch {
     46        ed_t *ed;
     47        td_t *tds;
     48        size_t td_count;
     49} ohci_batch_t;
     50
     51static void batch_control(usb_transfer_batch_t *instance,
     52    usb_direction_t data_dir, usb_direction_t status_dir);
    4353static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    4454static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    4555
    4656#define DEFAULT_ERROR_COUNT 3
    47 usb_transfer_batch_t * batch_get(
    48     ddf_fun_t *fun,
    49                 usb_target_t target,
    50     usb_transfer_type_t transfer_type,
    51                 size_t max_packet_size,
    52     usb_speed_t speed,
    53                 char *buffer,
    54                 size_t buffer_size,
    55                 char *setup_buffer,
    56                 size_t setup_size,
     57usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
     58    char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
    5759    usbhc_iface_transfer_in_callback_t func_in,
    58     usbhc_iface_transfer_out_callback_t func_out,
    59                 void *arg,
    60                 usb_device_keeper_t *manager
    61                 )
     60    usbhc_iface_transfer_out_callback_t func_out, void *arg)
    6261{
    6362#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
     
    7372        CHECK_NULL_DISPOSE_RETURN(instance,
    7473            "Failed to allocate batch instance.\n");
    75         usb_transfer_batch_init(instance, target, transfer_type, speed,
    76             max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
    77             func_in, func_out, arg, fun, NULL, NULL);
     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));
     81        CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
     82        bzero(data, sizeof(ohci_batch_t));
     83        instance->private_data = data;
     84
     85        /* we needs + 1 transfer descriptor as the last one won't be executed */
     86        data->td_count = 1 +
     87            ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
     88        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     89                data->td_count += 2;
     90        }
     91
     92        data->tds = malloc32(sizeof(td_t) * data->td_count);
     93        CHECK_NULL_DISPOSE_RETURN(data->tds,
     94            "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");
    78100
    79101        if (buffer_size > 0) {
     
    90112        }
    91113
    92 
    93114        return instance;
    94115}
     
    97118{
    98119        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);
    99125        free32(instance->transport_buffer);
    100         free32(instance->setup_buffer);
     126        free(data);
    101127        free(instance);
     128}
     129/*----------------------------------------------------------------------------*/
     130bool batch_is_complete(usb_transfer_batch_t *instance)
     131{
     132        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",
     137            instance, tds);
     138        size_t i = 0;
     139        for (; i < tds; ++i) {
     140                if (!td_is_finished(&data->tds[i]))
     141                        return false;
     142                instance->error = td_error(&data->tds[i]);
     143                /* FIXME: calculate real transfered size */
     144                instance->transfered_size = instance->buffer_size;
     145                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,
     150                }
     151        }
     152        return true;
    102153}
    103154/*----------------------------------------------------------------------------*/
     
    109160            instance->buffer_size);
    110161        instance->next_step = batch_call_out_and_dispose;
    111         /* TODO: implement */
     162        batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
    112163        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    113164}
     
    117168        assert(instance);
    118169        instance->next_step = batch_call_in_and_dispose;
    119         /* TODO: implement */
     170        batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
    120171        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    121172}
     
    124175{
    125176        assert(instance);
    126         instance->direction = USB_DIRECTION_IN;
     177        assert(instance->direction == USB_DIRECTION_IN);
    127178        instance->next_step = batch_call_in_and_dispose;
    128179        /* TODO: implement */
     
    133184{
    134185        assert(instance);
    135         instance->direction = USB_DIRECTION_OUT;
     186        assert(instance->direction == USB_DIRECTION_OUT);
    136187        /* We are data out, we are supposed to provide data */
    137188        memcpy(instance->transport_buffer, instance->buffer,
     
    160211}
    161212/*----------------------------------------------------------------------------*/
     213ed_t * batch_ed(usb_transfer_batch_t *instance)
     214{
     215        assert(instance);
     216        ohci_batch_t *data = instance->private_data;
     217        assert(data);
     218        return data->ed;
     219}
     220/*----------------------------------------------------------------------------*/
     221void batch_control(usb_transfer_batch_t *instance,
     222    usb_direction_t data_dir, usb_direction_t status_dir)
     223{
     224        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: %x:%x:%x:%x.\n", data->ed->status,
     230            data->ed->td_tail, data->ed->td_head, data->ed->next);
     231        int toggle = 0;
     232        /* setup stage */
     233        td_init(&data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
     234                instance->setup_size, toggle);
     235        td_set_next(&data->tds[0], &data->tds[1]);
     236        usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0].status,
     237            data->tds[0].cbp, data->tds[0].next, data->tds[0].be);
     238
     239        /* data stage */
     240        size_t td_current = 1;
     241        size_t remain_size = instance->buffer_size;
     242        char *transfer_buffer = instance->transport_buffer;
     243        while (remain_size > 0) {
     244                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     245                    OHCI_TD_MAX_TRANSFER : remain_size;
     246                toggle = 1 - toggle;
     247
     248                td_init(&data->tds[td_current], data_dir, transfer_buffer,
     249                    transfer_size, toggle);
     250                td_set_next(&data->tds[td_current], &data->tds[td_current + 1]);
     251                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
     252                    data->tds[td_current].status, data->tds[td_current].cbp,
     253                    data->tds[td_current].next, data->tds[td_current].be);
     254
     255                transfer_buffer += transfer_size;
     256                remain_size -= transfer_size;
     257                assert(td_current < data->td_count - 2);
     258                ++td_current;
     259        }
     260
     261        /* status stage */
     262        assert(td_current == data->td_count - 2);
     263        td_init(&data->tds[td_current], status_dir, NULL, 0, 1);
     264        usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n",
     265            data->tds[td_current].status, data->tds[td_current].cbp,
     266            data->tds[td_current].next, data->tds[td_current].be);
     267}
     268/*----------------------------------------------------------------------------*/
    162269/** Helper function calls callback and correctly disposes of batch structure.
    163270 *
Note: See TracChangeset for help on using the changeset viewer.