Changeset 651b352 in mainline for uspace/drv/ohci/batch.c


Ignore:
Timestamp:
2011-04-13T15:00:43Z (14 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8b4ce802
Parents:
4deca9b (diff), d6522dd (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:

Major rework

UHCI uses one buffer for both structures and data
OHCI uses new architecture that actually follows OHCI specification

File:
1 edited

Legend:

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

    r4deca9b r651b352  
    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; \
     
    7491            "Failed to allocate batch instance.\n");
    7592        usb_transfer_batch_init(instance, ep, buffer, NULL, buffer_size,
    76             NULL, setup_size, func_in, func_out, arg, fun, NULL);
    77 
    78         ohci_batch_t *data = malloc(sizeof(ohci_batch_t));
     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);
    79100        CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
    80         bzero(data, sizeof(ohci_batch_t));
    81101        instance->private_data = data;
    82102
    83         /* we needs + 1 transfer descriptor as the last one won't be executed */
    84         data->td_count = 1 +
     103        data->td_count =
    85104            ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
    86105        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     
    88107        }
    89108
    90         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);
    91111        CHECK_NULL_DISPOSE_RETURN(data->tds,
    92112            "Failed to allocate transfer descriptors.\n");
    93         bzero(data->tds, sizeof(td_t) * data->td_count);
    94 
    95         data->ed = malloc32(sizeof(ed_t));
    96         CHECK_NULL_DISPOSE_RETURN(data->ed,
    97             "Failed to allocate endpoint descriptor.\n");
    98 
    99         if (buffer_size > 0) {
    100                 instance->data_buffer = malloc32(buffer_size);
    101                 CHECK_NULL_DISPOSE_RETURN(instance->data_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,
    102128                    "Failed to allocate device accessible buffer.\n");
    103         }
    104 
    105         if (setup_size > 0) {
    106                 instance->setup_buffer = malloc32(setup_size);
    107                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    108                     "Failed to allocate device accessible setup buffer.\n");
     129                instance->setup_buffer = data->device_buffer;
     130                instance->data_buffer = data->device_buffer + setup_size;
    109131                memcpy(instance->setup_buffer, setup_buffer, setup_size);
    110132        }
     
    113135}
    114136/*----------------------------------------------------------------------------*/
    115 void batch_dispose(usb_transfer_batch_t *instance)
    116 {
    117         assert(instance);
    118         ohci_batch_t *data = instance->private_data;
    119         assert(data);
    120         free32(data->ed);
    121         free32(data->tds);
    122         free32(instance->setup_buffer);
    123         free32(instance->data_buffer);
    124         free(data);
    125         free(instance);
    126 }
    127 /*----------------------------------------------------------------------------*/
    128137bool batch_is_complete(usb_transfer_batch_t *instance)
    129138{
    130139        assert(instance);
    131         ohci_batch_t *data = instance->private_data;
    132         assert(data);
    133         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;
    134143        usb_log_debug("Batch(%p) checking %d td(s) for completion.\n",
    135144            instance, tds);
     
    139148        size_t i = 0;
    140149        for (; i < tds; ++i) {
     150                assert(data->tds[i] != NULL);
    141151                usb_log_debug("TD %d: %x:%x:%x:%x.\n", i,
    142                     data->tds[i].status, data->tds[i].cbp, data->tds[i].next,
    143                     data->tds[i].be);
    144                 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])) {
    145155                        return false;
    146156                }
    147                 instance->error = td_error(&data->tds[i]);
     157                instance->error = td_error(data->tds[i]);
    148158                /* FIXME: calculate real transfered size */
    149159                instance->transfered_size = instance->buffer_size;
    150160                if (instance->error != EOK) {
    151161                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    152                             instance, i, data->tds[i].status);
    153                         return true;
    154 //                      endpoint_toggle_set(instance->ep,
     162                            instance, i, data->tds[i]->status);
     163                        break;
    155164                }
    156165        }
     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
    157172        return true;
     173}
     174/*----------------------------------------------------------------------------*/
     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]);
    158181}
    159182/*----------------------------------------------------------------------------*/
     
    163186        /* We are data out, we are supposed to provide data */
    164187        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    165         instance->next_step = batch_call_out_and_dispose;
     188        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    166189        batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
    167190        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
     
    171194{
    172195        assert(instance);
    173         instance->next_step = batch_call_in_and_dispose;
     196        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    174197        batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
    175198        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
     
    179202{
    180203        assert(instance);
    181         instance->next_step = batch_call_in_and_dispose;
     204        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    182205        batch_data(instance);
    183206        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
     
    189212        /* We are data out, we are supposed to provide data */
    190213        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    191         instance->next_step = batch_call_out_and_dispose;
     214        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    192215        batch_data(instance);
    193216        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
     
    197220{
    198221        assert(instance);
    199         instance->next_step = batch_call_in_and_dispose;
     222        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    200223        batch_data(instance);
    201224        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     
    205228{
    206229        assert(instance);
    207         instance->next_step = batch_call_in_and_dispose;
     230        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    208231        batch_data(instance);
    209232        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     
    213236{
    214237        assert(instance);
    215         ohci_batch_t *data = instance->private_data;
     238        ohci_transfer_batch_t *data = instance->private_data;
    216239        assert(data);
    217240        return data->ed;
     
    222245{
    223246        assert(instance);
    224         ohci_batch_t *data = instance->private_data;
    225         assert(data);
    226         ed_init(data->ed, instance->ep);
    227         ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]);
    228         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,
    229250            data->ed->status, data->ed->td_tail, data->ed->td_head,
    230251            data->ed->next);
    231252        int toggle = 0;
    232253        /* setup stage */
    233         td_init(&data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
     254        td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
    234255                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);
     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);
    238259
    239260        /* data stage */
     
    246267                toggle = 1 - toggle;
    247268
    248                 td_init(&data->tds[td_current], data_dir, buffer,
     269                td_init(data->tds[td_current], data_dir, buffer,
    249270                    transfer_size, toggle);
    250                 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]);
    251272                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);
     273                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     274                    data->tds[td_current]->next, data->tds[td_current]->be);
    254275
    255276                buffer += transfer_size;
    256277                remain_size -= transfer_size;
    257                 assert(td_current < data->td_count - 2);
     278                assert(td_current < data->td_count - 1);
    258279                ++td_current;
    259280        }
    260281
    261282        /* status stage */
    262         assert(td_current == data->td_count - 2);
    263         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]);
    264286        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);
     287            data->tds[td_current]->status, data->tds[td_current]->cbp,
     288            data->tds[td_current]->next, data->tds[td_current]->be);
    267289}
    268290/*----------------------------------------------------------------------------*/
     
    270292{
    271293        assert(instance);
    272         ohci_batch_t *data = instance->private_data;
    273         assert(data);
    274         ed_init(data->ed, instance->ep);
    275         ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]);
    276         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,
    277297            data->ed->status, data->ed->td_tail, data->ed->td_head,
    278298            data->ed->next);
    279299
    280         /* data stage */
    281300        size_t td_current = 0;
    282301        size_t remain_size = instance->buffer_size;
     
    286305                    OHCI_TD_MAX_TRANSFER : remain_size;
    287306
    288                 td_init(&data->tds[td_current], instance->ep->direction,
     307                td_init(data->tds[td_current], instance->ep->direction,
    289308                    buffer, transfer_size, -1);
    290                 td_set_next(&data->tds[td_current], &data->tds[td_current + 1]);
     309                td_set_next(data->tds[td_current], data->tds[td_current + 1]);
    291310                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
    292                     data->tds[td_current].status, data->tds[td_current].cbp,
    293                     data->tds[td_current].next, data->tds[td_current].be);
     311                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     312                    data->tds[td_current]->next, data->tds[td_current]->be);
    294313
    295314                buffer += transfer_size;
     
    299318        }
    300319}
    301 /*----------------------------------------------------------------------------*/
    302 /** Helper function calls callback and correctly disposes of batch structure.
    303  *
    304  * @param[in] instance Batch structure to use.
    305  */
    306 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    307 {
    308         assert(instance);
    309         usb_transfer_batch_call_in(instance);
    310         batch_dispose(instance);
    311 }
    312 /*----------------------------------------------------------------------------*/
    313 /** Helper function calls callback and correctly disposes of batch structure.
    314  *
    315  * @param[in] instance Batch structure to use.
    316  */
    317 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    318 {
    319         assert(instance);
    320         usb_transfer_batch_call_out(instance);
    321         batch_dispose(instance);
    322 }
    323320/**
    324321 * @}
Note: See TracChangeset for help on using the changeset viewer.