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


Ignore:
Timestamp:
2011-04-17T19:17:55Z (13 years ago)
Author:
Matej Klonfar <maklf@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
63517c2, cfbbe1d3
Parents:
ef354b6 (diff), 8595577b (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:

new report structure fixes

File:
1 edited

Legend:

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

    ref354b6 re50cd7f  
    3939
    4040#include "batch.h"
     41#include "hcd_endpoint.h"
    4142#include "utils/malloc32.h"
    42 
    43 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    44 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    45 
    46 #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,
     43#include "hw_struct/endpoint_descriptor.h"
     44#include "hw_struct/transfer_descriptor.h"
     45
     46typedef struct ohci_transfer_batch {
     47        ed_t *ed;
     48        td_t **tds;
     49        size_t td_count;
     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/*----------------------------------------------------------------------------*/
     71static void batch_control(usb_transfer_batch_t *instance,
     72    usb_direction_t data_dir, usb_direction_t status_dir);
     73static void batch_data(usb_transfer_batch_t *instance);
     74/*----------------------------------------------------------------------------*/
     75usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
     76    char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
    5777    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                 )
     78    usbhc_iface_transfer_out_callback_t func_out, void *arg)
    6279{
    6380#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
     
    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_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);
    78 
    79         if (buffer_size > 0) {
    80                 instance->transport_buffer = malloc32(buffer_size);
    81                 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
     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);
     100        CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
     101        instance->private_data = data;
     102
     103        data->td_count =
     104            ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
     105        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     106                data->td_count += 2;
     107        }
     108
     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);
     111        CHECK_NULL_DISPOSE_RETURN(data->tds,
     112            "Failed to allocate transfer descriptors.\n");
     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,
    82128                    "Failed to allocate device accessible buffer.\n");
    83         }
    84 
    85         if (setup_size > 0) {
    86                 instance->setup_buffer = malloc32(setup_size);
    87                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    88                     "Failed to allocate device accessible setup buffer.\n");
     129                instance->setup_buffer = data->device_buffer;
     130                instance->data_buffer = data->device_buffer + setup_size;
    89131                memcpy(instance->setup_buffer, setup_buffer, setup_size);
    90132        }
    91133
    92 
    93134        return instance;
    94135}
    95136/*----------------------------------------------------------------------------*/
    96 void batch_dispose(usb_transfer_batch_t *instance)
    97 {
    98         assert(instance);
    99         free32(instance->transport_buffer);
    100         free32(instance->setup_buffer);
    101         free(instance);
     137bool batch_is_complete(usb_transfer_batch_t *instance)
     138{
     139        assert(instance);
     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",
     144            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);
     148        size_t i = 0;
     149        instance->transfered_size = instance->buffer_size;
     150        for (; i < tds; ++i) {
     151                assert(data->tds[i] != NULL);
     152                usb_log_debug("TD %d: %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])) {
     156                        return false;
     157                }
     158                instance->error = td_error(data->tds[i]);
     159                if (instance->error != EOK) {
     160                        usb_log_debug("Batch(%p) found error TD(%d):%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;
     168                }
     169        }
     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
     184        return true;
     185}
     186/*----------------------------------------------------------------------------*/
     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]);
    102193}
    103194/*----------------------------------------------------------------------------*/
     
    106197        assert(instance);
    107198        /* We are data out, we are supposed to provide data */
    108         memcpy(instance->transport_buffer, instance->buffer,
    109             instance->buffer_size);
    110         instance->next_step = batch_call_out_and_dispose;
    111         /* TODO: implement */
     199        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     200        instance->next_step = usb_transfer_batch_call_out_and_dispose;
     201        batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
    112202        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    113203}
     
    116206{
    117207        assert(instance);
    118         instance->next_step = batch_call_in_and_dispose;
    119         /* TODO: implement */
     208        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     209        batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
    120210        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    121211}
     
    124214{
    125215        assert(instance);
    126         instance->direction = USB_DIRECTION_IN;
    127         instance->next_step = batch_call_in_and_dispose;
    128         /* TODO: implement */
     216        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     217        batch_data(instance);
    129218        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    130219}
     
    133222{
    134223        assert(instance);
    135         instance->direction = USB_DIRECTION_OUT;
    136224        /* We are data out, we are supposed to provide data */
    137         memcpy(instance->transport_buffer, instance->buffer,
    138             instance->buffer_size);
    139         instance->next_step = batch_call_out_and_dispose;
    140         /* 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);
    141228        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    142229}
     
    145232{
    146233        assert(instance);
    147         instance->direction = USB_DIRECTION_IN;
    148         instance->next_step = batch_call_in_and_dispose;
    149         /* TODO: implement */
     234        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     235        batch_data(instance);
    150236        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    151237}
     
    154240{
    155241        assert(instance);
    156         instance->direction = USB_DIRECTION_IN;
    157         instance->next_step = batch_call_in_and_dispose;
    158         /* TODO: implement */
    159         usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    160 }
    161 /*----------------------------------------------------------------------------*/
    162 /** Helper function calls callback and correctly disposes of batch structure.
    163  *
    164  * @param[in] instance Batch structure to use.
    165  */
    166 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    167 {
    168         assert(instance);
    169         usb_transfer_batch_call_in(instance);
    170         batch_dispose(instance);
    171 }
    172 /*----------------------------------------------------------------------------*/
    173 /** Helper function calls callback and correctly disposes of batch structure.
    174  *
    175  * @param[in] instance Batch structure to use.
    176  */
    177 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    178 {
    179         assert(instance);
    180         usb_transfer_batch_call_out(instance);
    181         batch_dispose(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);
     247}
     248/*----------------------------------------------------------------------------*/
     249ed_t * batch_ed(usb_transfer_batch_t *instance)
     250{
     251        assert(instance);
     252        ohci_transfer_batch_t *data = instance->private_data;
     253        assert(data);
     254        return data->ed;
     255}
     256/*----------------------------------------------------------------------------*/
     257void batch_control(usb_transfer_batch_t *instance,
     258    usb_direction_t data_dir, usb_direction_t status_dir)
     259{
     260        assert(instance);
     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,
     264            data->ed->status, data->ed->td_tail, data->ed->td_head,
     265            data->ed->next);
     266        int toggle = 0;
     267        /* setup stage */
     268        td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
     269                instance->setup_size, toggle);
     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);
     273
     274        /* data stage */
     275        size_t td_current = 1;
     276        size_t remain_size = instance->buffer_size;
     277        char *buffer = instance->data_buffer;
     278        while (remain_size > 0) {
     279                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     280                    OHCI_TD_MAX_TRANSFER : remain_size;
     281                toggle = 1 - toggle;
     282
     283                td_init(data->tds[td_current], data_dir, buffer,
     284                    transfer_size, toggle);
     285                td_set_next(data->tds[td_current], data->tds[td_current + 1]);
     286                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
     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;
     291                remain_size -= transfer_size;
     292                assert(td_current < data->td_count - 1);
     293                ++td_current;
     294        }
     295
     296        /* status stage */
     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]);
     300        usb_log_debug("Created STATUS 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/*----------------------------------------------------------------------------*/
     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        }
    182333}
    183334/**
Note: See TracChangeset for help on using the changeset viewer.