Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 651b352 in mainline


Ignore:
Timestamp:
2011-04-13T15:00:43Z (11 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master
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

Location:
uspace
Files:
2 added
13 edited
2 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/ohci/Makefile

    r4deca9b r651b352  
    3434SOURCES = \
    3535        batch.c \
     36        endpoint_list.c \
    3637        hc.c \
     38        hcd_endpoint.c \
    3739        iface.c \
    3840        main.c \
     
    4042        pci.c \
    4143        root_hub.c \
    42         transfer_list.c \
    4344        hw_struct/endpoint_descriptor.c \
    4445        hw_struct/transfer_descriptor.c
  • 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 * @}
  • uspace/drv/ohci/batch.h

    r4deca9b r651b352  
    5050    void *arg);
    5151
    52 void batch_dispose(usb_transfer_batch_t *instance);
     52bool batch_is_complete(usb_transfer_batch_t *instance);
    5353
    54 bool batch_is_complete(usb_transfer_batch_t *instance);
     54void batch_commit(usb_transfer_batch_t *instance);
    5555
    5656void batch_control_write(usb_transfer_batch_t *instance);
  • uspace/drv/ohci/endpoint_list.c

    r4deca9b r651b352  
    3535#include <usb/debug.h>
    3636
    37 #include "transfer_list.h"
    38 
    39 static void transfer_list_remove_batch(
    40     transfer_list_t *instance, usb_transfer_batch_t *batch);
    41 /*----------------------------------------------------------------------------*/
     37#include "endpoint_list.h"
     38
    4239/** Initialize transfer list structures.
    4340 *
     
    4845 * Allocates memory for internal qh_t structure.
    4946 */
    50 int transfer_list_init(transfer_list_t *instance, const char *name)
     47int endpoint_list_init(endpoint_list_t *instance, const char *name)
    5148{
    5249        assert(instance);
     
    6259
    6360        ed_init(instance->list_head, NULL);
    64         list_initialize(&instance->batch_list);
     61        list_initialize(&instance->endpoint_list);
    6562        fibril_mutex_initialize(&instance->guard);
    6663        return EOK;
     
    7572 * Does not check whether this replaces an existing list .
    7673 */
    77 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
     74void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
    7875{
    7976        assert(instance);
     
    8279}
    8380/*----------------------------------------------------------------------------*/
    84 /** Submit transfer batch to the list and queue.
    85  *
    86  * @param[in] instance List to use.
    87  * @param[in] batch Transfer batch to submit.
    88  * @return Error code
    89  *
    90  * The batch is added to the end of the list and queue.
    91  */
    92 void transfer_list_add_batch(
    93     transfer_list_t *instance, usb_transfer_batch_t *batch)
    94 {
    95         assert(instance);
    96         assert(batch);
    97         usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
     81/** Submit transfer endpoint to the list and queue.
     82 *
     83 * @param[in] instance List to use.
     84 * @param[in] endpoint Transfer endpoint to submit.
     85 * @return Error code
     86 *
     87 * The endpoint is added to the end of the list and queue.
     88 */
     89void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
     90{
     91        assert(instance);
     92        assert(hcd_ep);
     93        usb_log_debug2("Queue %s: Adding endpoint(%p).\n",
     94            instance->name, hcd_ep);
    9895
    9996        fibril_mutex_lock(&instance->guard);
     
    10198        ed_t *last_ed = NULL;
    10299        /* Add to the hardware queue. */
    103         if (list_empty(&instance->batch_list)) {
     100        if (list_empty(&instance->endpoint_list)) {
    104101                /* There is nothing scheduled */
    105102                last_ed = instance->list_head;
    106103        } else {
    107104                /* There is something scheduled */
    108                 usb_transfer_batch_t *last = list_get_instance(
    109                     instance->batch_list.prev, usb_transfer_batch_t, link);
    110                 last_ed = batch_ed(last);
     105                hcd_endpoint_t *last = list_get_instance(
     106                    instance->endpoint_list.prev, hcd_endpoint_t, link);
     107                last_ed = last->ed;
    111108        }
    112109        /* keep link */
    113         batch_ed(batch)->next = last_ed->next;
    114         ed_append_ed(last_ed, batch_ed(batch));
     110        hcd_ep->ed->next = last_ed->next;
     111        ed_append_ed(last_ed, hcd_ep->ed);
    115112
    116113        asm volatile ("": : :"memory");
    117114
    118115        /* Add to the driver list */
    119         list_append(&batch->link, &instance->batch_list);
    120 
    121         usb_transfer_batch_t *first = list_get_instance(
    122             instance->batch_list.next, usb_transfer_batch_t, link);
    123         usb_log_debug("Batch(%p) added to list %s, first is %p(%p).\n",
    124                 batch, instance->name, first, batch_ed(first));
     116        list_append(&hcd_ep->link, &instance->endpoint_list);
     117
     118        hcd_endpoint_t *first = list_get_instance(
     119            instance->endpoint_list.next, hcd_endpoint_t, link);
     120        usb_log_debug("HCD EP(%p) added to list %s, first is %p(%p).\n",
     121                hcd_ep, instance->name, first, first->ed);
    125122        if (last_ed == instance->list_head) {
    126123                usb_log_debug2("%s head ED(%p-%p): %x:%x:%x:%x.\n",
     
    132129}
    133130/*----------------------------------------------------------------------------*/
    134 /** Create list for finished batches.
     131#if 0
     132/** Create list for finished endpoints.
    135133 *
    136134 * @param[in] instance List to use.
    137135 * @param[in] done list to fill
    138136 */
    139 void transfer_list_remove_finished(transfer_list_t *instance, link_t *done)
     137void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done)
    140138{
    141139        assert(instance);
     
    143141
    144142        fibril_mutex_lock(&instance->guard);
    145         usb_log_debug2("Checking list %s for completed batches(%d).\n",
    146             instance->name, list_count(&instance->batch_list));
    147         link_t *current = instance->batch_list.next;
    148         while (current != &instance->batch_list) {
     143        usb_log_debug2("Checking list %s for completed endpointes(%d).\n",
     144            instance->name, list_count(&instance->endpoint_list));
     145        link_t *current = instance->endpoint_list.next;
     146        while (current != &instance->endpoint_list) {
    149147                link_t *next = current->next;
    150                 usb_transfer_batch_t *batch =
    151                     list_get_instance(current, usb_transfer_batch_t, link);
    152 
    153                 if (batch_is_complete(batch)) {
     148                hcd_endpoint_t *endpoint =
     149                    list_get_instance(current, hcd_endpoint_t, link);
     150
     151                if (endpoint_is_complete(endpoint)) {
    154152                        /* Save for post-processing */
    155                         transfer_list_remove_batch(instance, batch);
     153                        endpoint_list_remove_endpoint(instance, endpoint);
    156154                        list_append(current, done);
    157155                }
     
    161159}
    162160/*----------------------------------------------------------------------------*/
    163 /** Walk the list and abort all batches.
    164  *
    165  * @param[in] instance List to use.
    166  */
    167 void transfer_list_abort_all(transfer_list_t *instance)
    168 {
    169         fibril_mutex_lock(&instance->guard);
    170         while (!list_empty(&instance->batch_list)) {
    171                 link_t *current = instance->batch_list.next;
    172                 usb_transfer_batch_t *batch =
    173                     list_get_instance(current, usb_transfer_batch_t, link);
    174                 transfer_list_remove_batch(instance, batch);
    175                 usb_transfer_batch_finish_error(batch, EIO);
    176         }
    177         fibril_mutex_unlock(&instance->guard);
    178 }
    179 /*----------------------------------------------------------------------------*/
    180 /** Remove a transfer batch from the list and queue.
    181  *
    182  * @param[in] instance List to use.
    183  * @param[in] batch Transfer batch to remove.
     161/** Walk the list and abort all endpointes.
     162 *
     163 * @param[in] instance List to use.
     164 */
     165void endpoint_list_abort_all(endpoint_list_t *instance)
     166{
     167        fibril_mutex_lock(&instance->guard);
     168        while (!list_empty(&instance->endpoint_list)) {
     169                link_t *current = instance->endpoint_list.next;
     170                hcd_endpoint_t *endpoint =
     171                    list_get_instance(current, hcd_endpoint_t, link);
     172                endpoint_list_remove_endpoint(instance, endpoint);
     173                hcd_endpoint_finish_error(endpoint, EIO);
     174        }
     175        fibril_mutex_unlock(&instance->guard);
     176}
     177#endif
     178/*----------------------------------------------------------------------------*/
     179/** Remove a transfer endpoint from the list and queue.
     180 *
     181 * @param[in] instance List to use.
     182 * @param[in] endpoint Transfer endpoint to remove.
    184183 * @return Error code
    185184 *
    186185 * Does not lock the transfer list, caller is responsible for that.
    187186 */
    188 void transfer_list_remove_batch(
    189     transfer_list_t *instance, usb_transfer_batch_t *batch)
     187void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
    190188{
    191189        assert(instance);
    192190        assert(instance->list_head);
    193         assert(batch);
    194         assert(batch_ed(batch));
    195         assert(fibril_mutex_is_locked(&instance->guard));
     191        assert(hcd_ep);
     192        assert(hcd_ep->ed);
     193
     194        fibril_mutex_lock(&instance->guard);
    196195
    197196        usb_log_debug2(
    198             "Queue %s: removing batch(%p).\n", instance->name, batch);
     197            "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep);
    199198
    200199        const char *qpos = NULL;
     200        ed_t *prev_ed;
    201201        /* Remove from the hardware queue */
    202         if (instance->batch_list.next == &batch->link) {
     202        if (instance->endpoint_list.next == &hcd_ep->link) {
    203203                /* I'm the first one here */
    204                 assert((instance->list_head->next & ED_NEXT_PTR_MASK)
    205                     == addr_to_phys(batch_ed(batch)));
    206                 instance->list_head->next = batch_ed(batch)->next;
     204                prev_ed = instance->list_head;
    207205                qpos = "FIRST";
    208206        } else {
    209                 usb_transfer_batch_t *prev =
    210                     list_get_instance(
    211                         batch->link.prev, usb_transfer_batch_t, link);
    212                 assert((batch_ed(prev)->next & ED_NEXT_PTR_MASK)
    213                     == addr_to_phys(batch_ed(batch)));
    214                 batch_ed(prev)->next = batch_ed(batch)->next;
     207                hcd_endpoint_t *prev =
     208                    list_get_instance(hcd_ep->link.prev, hcd_endpoint_t, link);
     209                prev_ed = prev->ed;
    215210                qpos = "NOT FIRST";
    216211        }
     212        assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed));
     213        prev_ed->next = hcd_ep->ed->next;
     214
    217215        asm volatile ("": : :"memory");
    218         usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n",
    219             batch, qpos, instance->name, batch_ed(batch)->next);
    220 
    221         /* Remove from the batch list */
    222         list_remove(&batch->link);
     216        usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n",
     217            hcd_ep, qpos, instance->name, hcd_ep->ed->next);
     218
     219        /* Remove from the endpoint list */
     220        list_remove(&hcd_ep->link);
     221        fibril_mutex_unlock(&instance->guard);
    223222}
    224223/**
  • uspace/drv/ohci/endpoint_list.h

    r4deca9b r651b352  
    3232 * @brief OHCI driver transfer list structure
    3333 */
    34 #ifndef DRV_OHCI_TRANSFER_LIST_H
    35 #define DRV_OHCI_TRANSFER_LIST_H
     34#ifndef DRV_OHCI_ENDPOINT_LIST_H
     35#define DRV_OHCI_ENDPOINT_LIST_H
    3636
    3737#include <fibril_synch.h>
    3838
    39 #include "batch.h"
     39#include "hcd_endpoint.h"
    4040#include "hw_struct/endpoint_descriptor.h"
    4141#include "utils/malloc32.h"
    4242
    43 typedef struct transfer_list
     43typedef struct endpoint_list
    4444{
    4545        fibril_mutex_t guard;
     
    4747        uint32_t list_head_pa;
    4848        const char *name;
    49         link_t batch_list;
    50 } transfer_list_t;
     49        link_t endpoint_list;
     50} endpoint_list_t;
    5151
    5252/** Dispose transfer list structures.
     
    5656 * Frees memory for internal qh_t structure.
    5757 */
    58 static inline void transfer_list_fini(transfer_list_t *instance)
     58static inline void endpoint_list_fini(endpoint_list_t *instance)
    5959{
    6060        assert(instance);
     
    6262}
    6363
    64 int transfer_list_init(transfer_list_t *instance, const char *name);
     64int endpoint_list_init(endpoint_list_t *instance, const char *name);
    6565
    66 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
     66void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next);
    6767
    68 void transfer_list_add_batch(transfer_list_t *instance, usb_transfer_batch_t *batch);
     68void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
    6969
    70 void transfer_list_remove_finished(transfer_list_t *instance, link_t *done);
     70void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
     71#if 0
     72void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done);
    7173
    72 void transfer_list_abort_all(transfer_list_t *instance);
     74void endpoint_list_abort_all(endpoint_list_t *instance);
     75#endif
    7376#endif
    7477/**
  • uspace/drv/ohci/hc.c

    r4deca9b r651b352  
    4343
    4444#include "hc.h"
     45#include "hcd_endpoint.h"
    4546
    4647static int interrupt_emulator(hc_t *instance);
     
    6768            &instance->manager, hub_address, hub_fun->handle);
    6869
    69         ret = usb_endpoint_manager_add_ep(&instance->ep_manager,
    70             hub_address, 0, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
    71             USB_SPEED_FULL, 64, 0);
     70        ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
     71            USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
    7272        if (ret != EOK) {
    7373                usb_log_error("Failed to add OHCI rh endpoint 0.\n");
     
    109109            ret, str_error(ret));
    110110
    111         instance->ddf_instance = fun;
    112111        usb_device_keeper_init(&instance->manager);
    113112        ret = usb_endpoint_manager_init(&instance->ep_manager,
     
    131130        }
    132131
    133         return EOK;
     132        list_initialize(&instance->pending_batches);
     133#undef CHECK_RET_RETURN
     134        return EOK;
     135}
     136/*----------------------------------------------------------------------------*/
     137int hc_add_endpoint(
     138    hc_t *instance, usb_address_t address, usb_endpoint_t endpoint,
     139    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
     140    size_t mps, size_t size, unsigned interval)
     141{
     142        endpoint_t *ep = malloc(sizeof(endpoint_t));
     143        if (ep == NULL)
     144                return ENOMEM;
     145        int ret =
     146            endpoint_init(ep, address, endpoint, direction, type, speed, mps);
     147        if (ret != EOK) {
     148                free(ep);
     149                return ret;
     150        }
     151
     152        hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
     153        if (hcd_ep == NULL) {
     154                endpoint_destroy(ep);
     155                return ENOMEM;
     156        }
     157
     158        ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
     159        if (ret != EOK) {
     160                hcd_endpoint_clear(ep);
     161                endpoint_destroy(ep);
     162                return ret;
     163        }
     164
     165        /* Enqueue hcd_ep */
     166        switch (ep->transfer_type) {
     167        case USB_TRANSFER_CONTROL:
     168                instance->registers->control &= ~C_CLE;
     169                endpoint_list_add_ep(
     170                    &instance->lists[ep->transfer_type], hcd_ep);
     171                instance->registers->control_current = 0;
     172                instance->registers->control |= C_CLE;
     173                break;
     174        case USB_TRANSFER_BULK:
     175                instance->registers->control &= ~C_BLE;
     176                endpoint_list_add_ep(
     177                    &instance->lists[ep->transfer_type], hcd_ep);
     178                instance->registers->control |= C_BLE;
     179                break;
     180        case USB_TRANSFER_ISOCHRONOUS:
     181        case USB_TRANSFER_INTERRUPT:
     182                instance->registers->control &= (~C_PLE & ~C_IE);
     183                endpoint_list_add_ep(
     184                    &instance->lists[ep->transfer_type], hcd_ep);
     185                instance->registers->control |= C_PLE | C_IE;
     186                break;
     187        default:
     188                break;
     189        }
     190
     191        return EOK;
     192}
     193/*----------------------------------------------------------------------------*/
     194int hc_remove_endpoint(hc_t *instance, usb_address_t address,
     195    usb_endpoint_t endpoint, usb_direction_t direction)
     196{
     197        assert(instance);
     198        fibril_mutex_lock(&instance->guard);
     199        endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
     200            address, endpoint, direction, NULL);
     201        if (ep == NULL) {
     202                usb_log_error("Endpoint unregister failed: No such EP.\n");
     203                fibril_mutex_unlock(&instance->guard);
     204                return ENOENT;
     205        }
     206
     207        hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
     208        if (hcd_ep) {
     209                /* Dequeue hcd_ep */
     210                switch (ep->transfer_type) {
     211                case USB_TRANSFER_CONTROL:
     212                        instance->registers->control &= ~C_CLE;
     213                        endpoint_list_remove_ep(
     214                            &instance->lists[ep->transfer_type], hcd_ep);
     215                        instance->registers->control_current = 0;
     216                        instance->registers->control |= C_CLE;
     217                        break;
     218                case USB_TRANSFER_BULK:
     219                        instance->registers->control &= ~C_BLE;
     220                        endpoint_list_remove_ep(
     221                            &instance->lists[ep->transfer_type], hcd_ep);
     222                        instance->registers->control |= C_BLE;
     223                        break;
     224                case USB_TRANSFER_ISOCHRONOUS:
     225                case USB_TRANSFER_INTERRUPT:
     226                        instance->registers->control &= (~C_PLE & ~C_IE);
     227                        endpoint_list_remove_ep(
     228                            &instance->lists[ep->transfer_type], hcd_ep);
     229                        instance->registers->control |= C_PLE | C_IE;
     230                        break;
     231                default:
     232                        break;
     233                }
     234                hcd_endpoint_clear(ep);
     235        } else {
     236                usb_log_warning("Endpoint without hcd equivalent structure.\n");
     237        }
     238        int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager,
     239            address, endpoint, direction);
     240        fibril_mutex_unlock(&instance->guard);
     241        return ret;
     242}
     243/*----------------------------------------------------------------------------*/
     244endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
     245    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw)
     246{
     247        assert(instance);
     248        fibril_mutex_lock(&instance->guard);
     249        endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
     250            address, endpoint, direction, bw);
     251        fibril_mutex_unlock(&instance->guard);
     252        return ep;
    134253}
    135254/*----------------------------------------------------------------------------*/
     
    146265
    147266        fibril_mutex_lock(&instance->guard);
     267        list_append(&batch->link, &instance->pending_batches);
     268        batch_commit(batch);
    148269        switch (batch->ep->transfer_type) {
    149270        case USB_TRANSFER_CONTROL:
    150                 instance->registers->control &= ~C_CLE;
    151                 transfer_list_add_batch(
    152                     instance->transfers[batch->ep->transfer_type], batch);
    153271                instance->registers->command_status |= CS_CLF;
    154                 usb_log_debug2("Set CS control transfer filled: %x.\n",
    155                         instance->registers->command_status);
    156                 instance->registers->control_current = 0;
    157                 instance->registers->control |= C_CLE;
    158272                break;
    159273        case USB_TRANSFER_BULK:
    160                 instance->registers->control &= ~C_BLE;
    161                 transfer_list_add_batch(
    162                     instance->transfers[batch->ep->transfer_type], batch);
    163274                instance->registers->command_status |= CS_BLF;
    164                 usb_log_debug2("Set bulk transfer filled: %x.\n",
    165                         instance->registers->command_status);
    166                 instance->registers->control |= C_BLE;
    167                 break;
    168         case USB_TRANSFER_INTERRUPT:
    169         case USB_TRANSFER_ISOCHRONOUS:
    170                 instance->registers->control &= (~C_PLE & ~C_IE);
    171                 transfer_list_add_batch(
    172                     instance->transfers[batch->ep->transfer_type], batch);
    173                 instance->registers->control |= C_PLE | C_IE;
    174                 usb_log_debug2("Added periodic transfer: %x.\n",
    175                     instance->registers->periodic_current);
    176275                break;
    177276        default:
    178277                break;
    179278        }
     279
    180280        fibril_mutex_unlock(&instance->guard);
    181281        return EOK;
     
    198298                usb_log_debug2("Periodic current: %p.\n",
    199299                    instance->registers->periodic_current);
    200                 LIST_INITIALIZE(done);
    201                 transfer_list_remove_finished(
    202                     &instance->transfers_interrupt, &done);
    203                 transfer_list_remove_finished(
    204                     &instance->transfers_isochronous, &done);
    205                 transfer_list_remove_finished(
    206                     &instance->transfers_control, &done);
    207                 transfer_list_remove_finished(
    208                     &instance->transfers_bulk, &done);
    209 
    210                 while (!list_empty(&done)) {
    211                         link_t *item = done.next;
    212                         list_remove(item);
     300
     301                link_t *current = instance->pending_batches.next;
     302                while (current != &instance->pending_batches) {
     303                        link_t *next = current->next;
    213304                        usb_transfer_batch_t *batch =
    214                             list_get_instance(item, usb_transfer_batch_t, link);
    215                         usb_transfer_batch_finish(batch);
     305                            usb_transfer_batch_from_link(current);
     306
     307                        if (batch_is_complete(batch)) {
     308                                list_remove(current);
     309                                usb_transfer_batch_finish(batch);
     310                        }
     311                        current = next;
    216312                }
    217313                fibril_mutex_unlock(&instance->guard);
     
    307403
    308404        /* Use queues */
    309         instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
     405        instance->registers->bulk_head =
     406            instance->lists[USB_TRANSFER_BULK].list_head_pa;
    310407        usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
    311             instance->transfers_bulk.list_head,
    312             instance->transfers_bulk.list_head_pa);
     408            instance->lists[USB_TRANSFER_BULK].list_head,
     409            instance->lists[USB_TRANSFER_BULK].list_head_pa);
    313410
    314411        instance->registers->control_head =
    315             instance->transfers_control.list_head_pa;
     412            instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
    316413        usb_log_debug2("Control HEAD set to: %p(%p).\n",
    317             instance->transfers_control.list_head,
    318             instance->transfers_control.list_head_pa);
     414            instance->lists[USB_TRANSFER_CONTROL].list_head,
     415            instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
    319416
    320417        /* Enable queues */
     
    347444        assert(instance);
    348445
    349 #define SETUP_TRANSFER_LIST(type, name) \
     446#define SETUP_ENDPOINT_LIST(type) \
    350447do { \
    351         int ret = transfer_list_init(&instance->type, name); \
     448        const char *name = usb_str_transfer_type(type); \
     449        int ret = endpoint_list_init(&instance->lists[type], name); \
    352450        if (ret != EOK) { \
    353                 usb_log_error("Failed(%d) to setup %s transfer list.\n", \
     451                usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
    354452                    ret, name); \
    355                 transfer_list_fini(&instance->transfers_isochronous); \
    356                 transfer_list_fini(&instance->transfers_interrupt); \
    357                 transfer_list_fini(&instance->transfers_control); \
    358                 transfer_list_fini(&instance->transfers_bulk); \
     453                endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \
     454                endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
     455                endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \
     456                endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \
    359457        } \
    360458} while (0)
    361459
    362         SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS");
    363         SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT");
    364         SETUP_TRANSFER_LIST(transfers_control, "CONTROL");
    365         SETUP_TRANSFER_LIST(transfers_bulk, "BULK");
    366 #undef SETUP_TRANSFER_LIST
    367         transfer_list_set_next(&instance->transfers_interrupt,
    368             &instance->transfers_isochronous);
    369 
    370         /* Assign pointers to be used during scheduling */
    371         instance->transfers[USB_TRANSFER_INTERRUPT] =
    372           &instance->transfers_interrupt;
    373         instance->transfers[USB_TRANSFER_ISOCHRONOUS] =
    374           &instance->transfers_interrupt;
    375         instance->transfers[USB_TRANSFER_CONTROL] =
    376           &instance->transfers_control;
    377         instance->transfers[USB_TRANSFER_BULK] =
    378           &instance->transfers_bulk;
     460        SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS);
     461        SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT);
     462        SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL);
     463        SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK);
     464#undef SETUP_ENDPOINT_LIST
     465        endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT],
     466            &instance->lists[USB_TRANSFER_ISOCHRONOUS]);
    379467
    380468        return EOK;
     
    397485        for (; i < 32; ++i) {
    398486                instance->hcca->int_ep[i] =
    399                     instance->transfers_interrupt.list_head_pa;
     487                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
    400488        }
    401489        usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
    402             instance->transfers_interrupt.list_head,
    403             instance->transfers_interrupt.list_head_pa);
     490            instance->lists[USB_TRANSFER_INTERRUPT].list_head,
     491            instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
    404492
    405493        return EOK;
  • uspace/drv/ohci/hc.h

    r4deca9b r651b352  
    4848#include "ohci_regs.h"
    4949#include "root_hub.h"
    50 #include "transfer_list.h"
     50#include "endpoint_list.h"
    5151#include "hw_struct/hcca.h"
    5252
    5353typedef struct hc {
    5454        ohci_regs_t *registers;
     55        hcca_t *hcca;
     56
    5557        usb_address_t rh_address;
    5658        rh_t rh;
    5759
    58         hcca_t *hcca;
     60        endpoint_list_t lists[4];
     61        link_t pending_batches;
    5962
    60         transfer_list_t transfers_isochronous;
    61         transfer_list_t transfers_interrupt;
    62         transfer_list_t transfers_control;
    63         transfer_list_t transfers_bulk;
    64 
    65         transfer_list_t *transfers[4];
    66 
    67         ddf_fun_t *ddf_instance;
    6863        usb_device_keeper_t manager;
    6964        usb_endpoint_manager_t ep_manager;
     
    7772     uintptr_t regs, size_t reg_size, bool interrupts);
    7873
    79 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
    80 
    81 void hc_interrupt(hc_t *instance, uint32_t status);
    82 
    8374/** Safely dispose host controller internal structures
    8475 *
     
    8677 */
    8778static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
     79
     80int hc_add_endpoint(hc_t *instance, usb_address_t address, usb_endpoint_t ep,
     81    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
     82    size_t max_packet_size, size_t size, unsigned interval);
     83
     84int hc_remove_endpoint(hc_t *instance, usb_address_t address,
     85    usb_endpoint_t endpoint, usb_direction_t direction);
     86
     87endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
     88    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw);
     89
     90int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
     91
     92void hc_interrupt(hc_t *instance, uint32_t status);
    8893
    8994/** Get and cast pointer to the driver data
  • uspace/drv/ohci/hw_struct/endpoint_descriptor.h

    r4deca9b r651b352  
    8181void ed_init(ed_t *instance, endpoint_t *ep);
    8282
    83 static inline void ed_add_tds(ed_t *instance, td_t *head, td_t *tail)
     83static inline void ed_set_td(ed_t *instance, td_t *td)
    8484{
    8585        assert(instance);
     86        uintptr_t pa = addr_to_phys(td);
    8687        instance->td_head =
    87             ((addr_to_phys(head) & ED_TDHEAD_PTR_MASK)
     88            ((pa & ED_TDHEAD_PTR_MASK)
    8889            | (instance->td_head & ~ED_TDHEAD_PTR_MASK));
    89         instance->td_tail = addr_to_phys(tail) & ED_TDTAIL_PTR_MASK;
     90        instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
     91}
     92
     93static inline void ed_set_end_td(ed_t *instance, td_t *td)
     94{
     95        assert(instance);
     96        uintptr_t pa = addr_to_phys(td);
     97        instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
    9098}
    9199
  • uspace/drv/ohci/iface.c

    r4deca9b r651b352  
    5555
    5656        size_t res_bw;
    57         endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,
     57        endpoint_t *ep = hc_get_endpoint(*hc,
    5858            target.address, target.endpoint, direction, &res_bw);
    5959        if (ep == NULL) {
     
    164164        }
    165165        const size_t size = max_packet_size;
    166         int ret;
    167166
    168167        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
     
    170169            usb_str_speed(speed), direction, size, max_packet_size, interval);
    171170
    172         endpoint_t *ep = malloc(sizeof(endpoint_t));
    173         if (ep == NULL)
    174                 return ENOMEM;
    175         ret = endpoint_init(ep, address, endpoint, direction,
    176             transfer_type, speed, max_packet_size);
    177         if (ret != EOK) {
    178                 free(ep);
    179                 return ret;
    180         }
    181 
    182         ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
    183         if (ret != EOK) {
    184                 endpoint_destroy(ep);
    185         }
    186         return ret;
     171        return hc_add_endpoint(hc, address, endpoint, speed, transfer_type,
     172            direction, max_packet_size, size, interval);
    187173}
    188174/*----------------------------------------------------------------------------*/
     
    195181        usb_log_debug("Unregister endpoint %d:%d %d.\n",
    196182            address, endpoint, direction);
    197         return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
    198             endpoint, direction);
     183        return hc_remove_endpoint(hc, address, endpoint, direction);
    199184}
    200185/*----------------------------------------------------------------------------*/
     
    228213        ret = hc_schedule(hc, batch);
    229214        if (ret != EOK) {
    230                 batch_dispose(batch);
     215                usb_transfer_batch_dispose(batch);
    231216        }
    232217        return ret;
     
    262247        ret = hc_schedule(hc, batch);
    263248        if (ret != EOK) {
    264                 batch_dispose(batch);
     249                usb_transfer_batch_dispose(batch);
    265250        }
    266251        return ret;
     
    296281        ret = hc_schedule(hc, batch);
    297282        if (ret != EOK) {
    298                 batch_dispose(batch);
     283                usb_transfer_batch_dispose(batch);
    299284        }
    300285        return ret;
     
    330315        ret = hc_schedule(hc, batch);
    331316        if (ret != EOK) {
    332                 batch_dispose(batch);
     317                usb_transfer_batch_dispose(batch);
    333318        }
    334319        return ret;
     
    346331 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    347332 *      and deallocated by the caller).
    348  * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
     333 * @param[in] setup_size Size of @p setup_packet buffer in bytes.
    349334 * @param[in] data_buffer Data buffer (in USB endianess, allocated and
    350335 *      deallocated by the caller).
    351  * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
     336 * @param[in] size Size of @p data_buffer buffer in bytes.
    352337 * @param[in] callback Callback to be issued once the transfer is complete.
    353338 * @param[in] arg Pass-through argument to the callback.
     
    370355        ret = hc_schedule(hc, batch);
    371356        if (ret != EOK) {
    372                 batch_dispose(batch);
     357                usb_transfer_batch_dispose(batch);
    373358        }
    374359        return ret;
     
    386371 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    387372 *      and deallocated by the caller).
    388  * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
     373 * @param[in] setup_size Size of @p setup_packet buffer in bytes.
    389374 * @param[in] data_buffer Buffer where to store the data (in USB endianess,
    390375 *      allocated and deallocated by the caller).
    391  * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
     376 * @param[in] size Size of @p data_buffer buffer in bytes.
    392377 * @param[in] callback Callback to be issued once the transfer is complete.
    393378 * @param[in] arg Pass-through argument to the callback.
     
    409394        ret = hc_schedule(hc, batch);
    410395        if (ret != EOK) {
    411                 batch_dispose(batch);
     396                usb_transfer_batch_dispose(batch);
    412397        }
    413398        return ret;
  • uspace/drv/uhci-hcd/batch.c

    r4deca9b r651b352  
    4545#define DEFAULT_ERROR_COUNT 3
    4646
    47 typedef struct uhci_batch {
     47typedef struct uhci_transfer_batch {
    4848        qh_t *qh;
    4949        td_t *tds;
     50        void *device_buffer;
    5051        size_t td_count;
    51 } uhci_batch_t;
     52} uhci_transfer_batch_t;
     53/*----------------------------------------------------------------------------*/
     54static void uhci_transfer_batch_dispose(void *uhci_batch)
     55{
     56        uhci_transfer_batch_t *instance = uhci_batch;
     57        assert(instance);
     58        free32(instance->device_buffer);
     59        free(instance);
     60}
     61/*----------------------------------------------------------------------------*/
    5262
    5363static void batch_control(usb_transfer_batch_t *instance,
    5464    usb_packet_id data_stage, usb_packet_id status_stage);
    5565static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
    56 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    57 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    58 
    5966
    6067/** Allocate memory and initialize internal data structure.
     
    8895        if (ptr == NULL) { \
    8996                usb_log_error(message); \
    90                 if (instance) { \
    91                         batch_dispose(instance); \
     97                if (uhci_data) { \
     98                        uhci_transfer_batch_dispose(uhci_data); \
    9299                } \
    93100                return NULL; \
    94101        } else (void)0
    95102
     103        uhci_transfer_batch_t *uhci_data =
     104            malloc(sizeof(uhci_transfer_batch_t));
     105        CHECK_NULL_DISPOSE_RETURN(uhci_data,
     106            "Failed to allocate UHCI batch.\n");
     107        bzero(uhci_data, sizeof(uhci_transfer_batch_t));
     108
     109        uhci_data->td_count =
     110            (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
     111        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     112                uhci_data->td_count += 2;
     113        }
     114
     115        assert((sizeof(td_t) % 16) == 0);
     116        const size_t total_size = (sizeof(td_t) * uhci_data->td_count)
     117            + sizeof(qh_t) + setup_size + buffer_size;
     118        uhci_data->device_buffer = malloc32(total_size);
     119        CHECK_NULL_DISPOSE_RETURN(uhci_data->device_buffer,
     120            "Failed to allocate UHCI buffer.\n");
     121        bzero(uhci_data->device_buffer, total_size);
     122
     123        uhci_data->tds = uhci_data->device_buffer;
     124        uhci_data->qh =
     125            (uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count));
     126
     127        qh_init(uhci_data->qh);
     128        qh_set_element_td(uhci_data->qh, addr_to_phys(uhci_data->tds));
     129
    96130        usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
    97131        CHECK_NULL_DISPOSE_RETURN(instance,
    98132            "Failed to allocate batch instance.\n");
     133        void *setup =
     134            uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count)
     135            + sizeof(qh_t);
     136        void *data_buffer = setup + setup_size;
    99137        usb_target_t target =
    100138            { .address = ep->address, .endpoint = ep->endpoint };
    101         usb_transfer_batch_init(instance, ep,
    102             buffer, NULL, buffer_size, NULL, setup_size,
    103             func_in, func_out, arg, fun, NULL);
    104 
    105 
    106         uhci_batch_t *data = malloc(sizeof(uhci_batch_t));
    107         CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
    108         bzero(data, sizeof(uhci_batch_t));
    109         instance->private_data = data;
    110 
    111         data->td_count =
    112             (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
    113         if (ep->transfer_type == USB_TRANSFER_CONTROL) {
    114                 data->td_count += 2;
    115         }
    116 
    117         data->tds = malloc32(sizeof(td_t) * data->td_count);
    118         CHECK_NULL_DISPOSE_RETURN(
    119             data->tds, "Failed to allocate transfer descriptors.\n");
    120         bzero(data->tds, sizeof(td_t) * data->td_count);
    121 
    122         data->qh = malloc32(sizeof(qh_t));
    123         CHECK_NULL_DISPOSE_RETURN(data->qh,
    124             "Failed to allocate batch queue head.\n");
    125         qh_init(data->qh);
    126         qh_set_element_td(data->qh, addr_to_phys(data->tds));
    127 
    128         if (buffer_size > 0) {
    129                 instance->data_buffer = malloc32(buffer_size);
    130                 CHECK_NULL_DISPOSE_RETURN(instance->data_buffer,
    131                     "Failed to allocate device accessible buffer.\n");
    132         }
    133 
    134         if (setup_size > 0) {
    135                 instance->setup_buffer = malloc32(setup_size);
    136                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    137                     "Failed to allocate device accessible setup buffer.\n");
    138                 memcpy(instance->setup_buffer, setup_buffer, setup_size);
    139         }
    140 
     139        usb_transfer_batch_init(instance, ep, buffer, data_buffer, buffer_size,
     140            setup, setup_size, func_in, func_out, arg, fun,
     141            uhci_data, uhci_transfer_batch_dispose);
     142
     143        memcpy(instance->setup_buffer, setup_buffer, setup_size);
    141144        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
    142145            instance, target.address, target.endpoint);
     
    156159{
    157160        assert(instance);
    158         uhci_batch_t *data = instance->private_data;
     161        uhci_transfer_batch_t *data = instance->private_data;
    159162        assert(data);
    160163
     
    203206        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    204207        batch_control(instance, USB_PID_OUT, USB_PID_IN);
    205         instance->next_step = batch_call_out_and_dispose;
     208        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    206209        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    207210}
     
    217220        assert(instance);
    218221        batch_control(instance, USB_PID_IN, USB_PID_OUT);
    219         instance->next_step = batch_call_in_and_dispose;
     222        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    220223        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    221224}
     
    231234        assert(instance);
    232235        batch_data(instance, USB_PID_IN);
    233         instance->next_step = batch_call_in_and_dispose;
     236        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    234237        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    235238}
     
    247250        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    248251        batch_data(instance, USB_PID_OUT);
    249         instance->next_step = batch_call_out_and_dispose;
     252        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    250253        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    251254}
     
    261264        assert(instance);
    262265        batch_data(instance, USB_PID_IN);
    263         instance->next_step = batch_call_in_and_dispose;
     266        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    264267        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    265268}
     
    277280        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    278281        batch_data(instance, USB_PID_OUT);
    279         instance->next_step = batch_call_out_and_dispose;
     282        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    280283        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
    281284}
     
    292295{
    293296        assert(instance);
    294         uhci_batch_t *data = instance->private_data;
     297        uhci_transfer_batch_t *data = instance->private_data;
    295298        assert(data);
    296299
     
    344347{
    345348        assert(instance);
    346         uhci_batch_t *data = instance->private_data;
     349        uhci_transfer_batch_t *data = instance->private_data;
    347350        assert(data);
    348351        assert(data->td_count >= 2);
     
    396399{
    397400        assert(instance);
    398         uhci_batch_t *data = instance->private_data;
     401        uhci_transfer_batch_t *data = instance->private_data;
    399402        assert(data);
    400403        return data->qh;
    401404}
    402 /*----------------------------------------------------------------------------*/
    403 /** Helper function, calls callback and correctly destroys batch structure.
    404  *
    405  * @param[in] instance Batch structure to use.
    406  */
    407 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    408 {
    409         assert(instance);
    410         usb_transfer_batch_call_in(instance);
    411         batch_dispose(instance);
    412 }
    413 /*----------------------------------------------------------------------------*/
    414 /** Helper function calls callback and correctly destroys batch structure.
    415  *
    416  * @param[in] instance Batch structure to use.
    417  */
    418 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    419 {
    420         assert(instance);
    421         usb_transfer_batch_call_out(instance);
    422         batch_dispose(instance);
    423 }
    424 /*----------------------------------------------------------------------------*/
    425 /** Correctly dispose all used data structures.
    426  *
    427  * @param[in] instance Batch structure to use.
    428  */
    429 void batch_dispose(usb_transfer_batch_t *instance)
    430 {
    431         assert(instance);
    432         uhci_batch_t *data = instance->private_data;
    433         assert(data);
    434         usb_log_debug("Batch(%p) disposing.\n", instance);
    435         /* free32 is NULL safe */
    436         free32(data->tds);
    437         free32(data->qh);
    438         free32(instance->setup_buffer);
    439         free32(instance->data_buffer);
    440         free(data);
    441         free(instance);
    442 }
    443405/**
    444406 * @}
  • uspace/drv/uhci-hcd/iface.c

    r4deca9b r651b352  
    195195        ret = hc_schedule(hc, batch);
    196196        if (ret != EOK) {
    197                 batch_dispose(batch);
     197                usb_transfer_batch_dispose(batch);
    198198        }
    199199        return ret;
     
    223223        ret = hc_schedule(hc, batch);
    224224        if (ret != EOK) {
    225                 batch_dispose(batch);
     225                usb_transfer_batch_dispose(batch);
    226226        }
    227227        return ret;
     
    251251        ret = hc_schedule(hc, batch);
    252252        if (ret != EOK) {
    253                 batch_dispose(batch);
     253                usb_transfer_batch_dispose(batch);
    254254        }
    255255        return ret;
     
    279279        ret = hc_schedule(hc, batch);
    280280        if (ret != EOK) {
    281                 batch_dispose(batch);
     281                usb_transfer_batch_dispose(batch);
    282282        }
    283283        return ret;
     
    312312        ret = hc_schedule(hc, batch);
    313313        if (ret != EOK) {
    314                 batch_dispose(batch);
     314                usb_transfer_batch_dispose(batch);
    315315        }
    316316        return ret;
     
    344344        ret = hc_schedule(hc, batch);
    345345        if (ret != EOK) {
    346                 batch_dispose(batch);
     346                usb_transfer_batch_dispose(batch);
    347347        }
    348348        return ret;
  • uspace/lib/usb/include/usb/host/batch.h

    r4deca9b r651b352  
    5858        ddf_fun_t *fun;
    5959        void *private_data;
     60        void (*private_data_dtor)(void *p_data);
    6061};
    6162
    6263void usb_transfer_batch_init(
    6364    usb_transfer_batch_t *instance,
    64                 endpoint_t *ep,
     65    endpoint_t *ep,
    6566    char *buffer,
    6667    char *data_buffer,
     
    7273    void *arg,
    7374    ddf_fun_t *fun,
    74     void *private_data
     75    void *private_data,
     76    void (*private_data_dtor)(void *p_data)
    7577);
    7678
    77 static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l)
    78 {
    79         assert(l);
    80         return list_get_instance(l, usb_transfer_batch_t, link);
    81 }
    82 
    83 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
    84 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
     79void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance);
     80void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    8581void usb_transfer_batch_finish(usb_transfer_batch_t *instance);
     82void usb_transfer_batch_dispose(usb_transfer_batch_t *instance);
    8683
    8784static inline void usb_transfer_batch_finish_error(
     
    9390}
    9491
     92static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l)
     93{
     94        assert(l);
     95        return list_get_instance(l, usb_transfer_batch_t, link);
     96}
     97
    9598#endif
    9699/**
  • uspace/lib/usb/include/usb/host/endpoint.h

    r4deca9b r651b352  
    5454        fibril_condvar_t avail;
    5555        volatile bool active;
     56        struct {
     57                void *data;
     58                int (*toggle_get)(void *);
     59                void (*toggle_set)(void *, int);
     60        } hc_data;
    5661} endpoint_t;
    5762
     
    6166
    6267void endpoint_destroy(endpoint_t *instance);
     68
     69void endpoint_set_hc_data(endpoint_t *instance,
     70    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int));
     71
     72void endpoint_clear_hc_data(endpoint_t *instance);
    6373
    6474void endpoint_use(endpoint_t *instance);
  • uspace/lib/usb/src/host/batch.c

    r4deca9b r651b352  
    3939#include <usb/host/batch.h>
    4040
     41void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
     42void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
     43
    4144void usb_transfer_batch_init(
    4245    usb_transfer_batch_t *instance,
    43                 endpoint_t *ep,
     46    endpoint_t *ep,
    4447    char *buffer,
    4548    char *data_buffer,
     
    5154    void *arg,
    5255    ddf_fun_t *fun,
    53     void *private_data
     56    void *private_data,
     57    void (*private_data_dtor)(void *p_data)
    5458    )
    5559{
     
    6771        instance->fun = fun;
    6872        instance->private_data = private_data;
     73        instance->private_data_dtor = private_data_dtor;
    6974        instance->transfered_size = 0;
    7075        instance->next_step = NULL;
    7176        instance->error = EOK;
    7277        endpoint_use(instance->ep);
     78}
     79/*----------------------------------------------------------------------------*/
     80/** Helper function, calls callback and correctly destroys batch structure.
     81 *
     82 * @param[in] instance Batch structure to use.
     83 */
     84void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance)
     85{
     86        assert(instance);
     87        usb_transfer_batch_call_in(instance);
     88        usb_transfer_batch_dispose(instance);
     89}
     90/*----------------------------------------------------------------------------*/
     91/** Helper function calls callback and correctly destroys batch structure.
     92 *
     93 * @param[in] instance Batch structure to use.
     94 */
     95void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance)
     96{
     97        assert(instance);
     98        usb_transfer_batch_call_out(instance);
     99        usb_transfer_batch_dispose(instance);
    73100}
    74101/*----------------------------------------------------------------------------*/
     
    129156            instance->error, instance->arg);
    130157}
     158/*----------------------------------------------------------------------------*/
     159/** Correctly dispose all used data structures.
     160 *
     161 * @param[in] instance Batch structure to use.
     162 */
     163void usb_transfer_batch_dispose(usb_transfer_batch_t *instance)
     164{
     165        assert(instance);
     166        usb_log_debug("Batch(%p) disposing.\n", instance);
     167        if (instance->private_data) {
     168                assert(instance->private_data_dtor);
     169                instance->private_data_dtor(instance->private_data);
     170        }
     171        free(instance);
     172}
    131173/**
    132174 * @}
  • uspace/lib/usb/src/host/endpoint.c

    r4deca9b r651b352  
    6363}
    6464/*----------------------------------------------------------------------------*/
     65void endpoint_set_hc_data(endpoint_t *instance,
     66    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
     67{
     68        assert(instance);
     69        instance->hc_data.data = data;
     70        instance->hc_data.toggle_get = toggle_get;
     71        instance->hc_data.toggle_set = toggle_set;
     72}
     73/*----------------------------------------------------------------------------*/
     74void endpoint_clear_hc_data(endpoint_t *instance)
     75{
     76        assert(instance);
     77        instance->hc_data.data = NULL;
     78        instance->hc_data.toggle_get = NULL;
     79        instance->hc_data.toggle_set = NULL;
     80}
     81/*----------------------------------------------------------------------------*/
    6582void endpoint_use(endpoint_t *instance)
    6683{
     
    85102{
    86103        assert(instance);
     104        if (instance->hc_data.toggle_get)
     105                instance->toggle =
     106                    instance->hc_data.toggle_get(instance->hc_data.data);
    87107        return (int)instance->toggle;
    88108}
     
    92112        assert(instance);
    93113        assert(toggle == 0 || toggle == 1);
     114        if (instance->hc_data.toggle_set)
     115                instance->hc_data.toggle_set(instance->hc_data.data, toggle);
    94116        instance->toggle = toggle;
    95117}
Note: See TracChangeset for help on using the changeset viewer.