Changeset a39cfb8 in mainline for uspace/drv


Ignore:
Timestamp:
2011-04-14T07:54:33Z (15 years ago)
Author:
Matus Dekanek <smekideki@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e05d6c3
Parents:
3f3afb9 (diff), 34e8bab (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:

merge from development

Location:
uspace/drv
Files:
26 edited
4 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/isa/isa.c

    r3f3afb9 ra39cfb8  
    8383static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
    8484{
    85         // TODO
     85        /* TODO */
    8686
    8787        return false;
  • uspace/drv/ohci/Makefile

    r3f3afb9 ra39cfb8  
    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

    r3f3afb9 ra39cfb8  
    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; \
     
    7390        CHECK_NULL_DISPOSE_RETURN(instance,
    7491            "Failed to allocate batch instance.\n");
    75         usb_target_t target =
    76             { .address = ep->address, .endpoint = ep->endpoint };
    77         usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed,
    78             ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
    79             func_in, func_out, arg, fun, ep, NULL);
    80 
    81         ohci_batch_t *data = malloc(sizeof(ohci_batch_t));
     92        usb_transfer_batch_init(instance, ep, buffer, NULL, buffer_size,
     93            NULL, setup_size, func_in, func_out, arg, fun, NULL,
     94            ohci_transfer_batch_dispose);
     95
     96        hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
     97        assert(hcd_ep);
     98
     99        ohci_transfer_batch_t *data = calloc(sizeof(ohci_transfer_batch_t), 1);
    82100        CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
    83         bzero(data, sizeof(ohci_batch_t));
    84101        instance->private_data = data;
    85102
    86         /* we needs + 1 transfer descriptor as the last one won't be executed */
    87         data->td_count = 1 +
     103        data->td_count =
    88104            ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
    89105        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     
    91107        }
    92108
    93         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);
    94111        CHECK_NULL_DISPOSE_RETURN(data->tds,
    95112            "Failed to allocate transfer descriptors.\n");
    96         bzero(data->tds, sizeof(td_t) * data->td_count);
    97 
    98         data->ed = malloc32(sizeof(ed_t));
    99         CHECK_NULL_DISPOSE_RETURN(data->ed,
    100             "Failed to allocate endpoint descriptor.\n");
    101 
    102         if (buffer_size > 0) {
    103                 instance->transport_buffer = malloc32(buffer_size);
    104                 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
     113
     114        data->tds[0] = hcd_ep->td;
     115        data->leave_td = 0;
     116        unsigned i = 1;
     117        for (; i <= data->td_count; ++i) {
     118                data->tds[i] = malloc32(sizeof(td_t));
     119                CHECK_NULL_DISPOSE_RETURN(data->tds[i],
     120                    "Failed to allocate TD %d.\n", i );
     121        }
     122
     123        data->ed = hcd_ep->ed;
     124
     125        if (setup_size + buffer_size > 0) {
     126                data->device_buffer = malloc32(setup_size + buffer_size);
     127                CHECK_NULL_DISPOSE_RETURN(data->device_buffer,
    105128                    "Failed to allocate device accessible buffer.\n");
    106         }
    107 
    108         if (setup_size > 0) {
    109                 instance->setup_buffer = malloc32(setup_size);
    110                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    111                     "Failed to allocate device accessible setup buffer.\n");
     129                instance->setup_buffer = data->device_buffer;
     130                instance->data_buffer = data->device_buffer + setup_size;
    112131                memcpy(instance->setup_buffer, setup_buffer, setup_size);
    113132        }
     
    116135}
    117136/*----------------------------------------------------------------------------*/
    118 void batch_dispose(usb_transfer_batch_t *instance)
    119 {
    120         assert(instance);
    121         ohci_batch_t *data = instance->private_data;
    122         assert(data);
    123         free32(data->ed);
    124         free32(data->tds);
    125         free32(instance->setup_buffer);
    126         free32(instance->transport_buffer);
    127         free(data);
    128         free(instance);
    129 }
    130 /*----------------------------------------------------------------------------*/
    131137bool batch_is_complete(usb_transfer_batch_t *instance)
    132138{
    133139        assert(instance);
    134         ohci_batch_t *data = instance->private_data;
    135         assert(data);
    136         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;
    137143        usb_log_debug("Batch(%p) checking %d td(s) for completion.\n",
    138144            instance, tds);
     
    142148        size_t i = 0;
    143149        for (; i < tds; ++i) {
     150                assert(data->tds[i] != NULL);
    144151                usb_log_debug("TD %d: %x:%x:%x:%x.\n", i,
    145                     data->tds[i].status, data->tds[i].cbp, data->tds[i].next,
    146                     data->tds[i].be);
    147                 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])) {
    148155                        return false;
    149156                }
    150                 instance->error = td_error(&data->tds[i]);
     157                instance->error = td_error(data->tds[i]);
    151158                /* FIXME: calculate real transfered size */
    152159                instance->transfered_size = instance->buffer_size;
    153160                if (instance->error != EOK) {
    154161                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    155                             instance, i, data->tds[i].status);
    156                         return true;
    157 //                      endpoint_toggle_set(instance->ep,
     162                            instance, i, data->tds[i]->status);
     163                        break;
    158164                }
    159165        }
     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
    160172        return true;
    161173}
    162174/*----------------------------------------------------------------------------*/
     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]);
     181}
     182/*----------------------------------------------------------------------------*/
    163183void batch_control_write(usb_transfer_batch_t *instance)
    164184{
    165185        assert(instance);
    166186        /* We are data out, we are supposed to provide data */
    167         memcpy(instance->transport_buffer, instance->buffer,
    168             instance->buffer_size);
    169         instance->next_step = batch_call_out_and_dispose;
     187        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     188        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    170189        batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
    171190        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
     
    175194{
    176195        assert(instance);
    177         instance->next_step = batch_call_in_and_dispose;
     196        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    178197        batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
    179198        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
     
    183202{
    184203        assert(instance);
    185         assert(instance->direction == USB_DIRECTION_IN);
    186         instance->next_step = batch_call_in_and_dispose;
     204        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    187205        batch_data(instance);
    188206        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
     
    192210{
    193211        assert(instance);
    194         assert(instance->direction == USB_DIRECTION_OUT);
    195212        /* We are data out, we are supposed to provide data */
    196         memcpy(instance->transport_buffer, instance->buffer,
    197             instance->buffer_size);
    198         instance->next_step = batch_call_out_and_dispose;
     213        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     214        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    199215        batch_data(instance);
    200216        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
     
    204220{
    205221        assert(instance);
    206         instance->direction = USB_DIRECTION_IN;
    207         instance->next_step = batch_call_in_and_dispose;
     222        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    208223        batch_data(instance);
    209224        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     
    213228{
    214229        assert(instance);
    215         instance->direction = USB_DIRECTION_IN;
    216         instance->next_step = batch_call_in_and_dispose;
     230        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    217231        batch_data(instance);
    218232        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     
    222236{
    223237        assert(instance);
    224         ohci_batch_t *data = instance->private_data;
     238        ohci_transfer_batch_t *data = instance->private_data;
    225239        assert(data);
    226240        return data->ed;
     
    231245{
    232246        assert(instance);
    233         ohci_batch_t *data = instance->private_data;
    234         assert(data);
    235         ed_init(data->ed, instance->ep);
    236         ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]);
    237         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,
    238250            data->ed->status, data->ed->td_tail, data->ed->td_head,
    239251            data->ed->next);
    240252        int toggle = 0;
    241253        /* setup stage */
    242         td_init(&data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
     254        td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
    243255                instance->setup_size, toggle);
    244         td_set_next(&data->tds[0], &data->tds[1]);
    245         usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0].status,
    246             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);
    247259
    248260        /* data stage */
    249261        size_t td_current = 1;
    250262        size_t remain_size = instance->buffer_size;
    251         char *transfer_buffer = instance->transport_buffer;
     263        char *buffer = instance->data_buffer;
    252264        while (remain_size > 0) {
    253265                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     
    255267                toggle = 1 - toggle;
    256268
    257                 td_init(&data->tds[td_current], data_dir, transfer_buffer,
     269                td_init(data->tds[td_current], data_dir, buffer,
    258270                    transfer_size, toggle);
    259                 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]);
    260272                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
    261                     data->tds[td_current].status, data->tds[td_current].cbp,
    262                     data->tds[td_current].next, data->tds[td_current].be);
    263 
    264                 transfer_buffer += transfer_size;
     273                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     274                    data->tds[td_current]->next, data->tds[td_current]->be);
     275
     276                buffer += transfer_size;
    265277                remain_size -= transfer_size;
    266                 assert(td_current < data->td_count - 2);
     278                assert(td_current < data->td_count - 1);
    267279                ++td_current;
    268280        }
    269281
    270282        /* status stage */
    271         assert(td_current == data->td_count - 2);
    272         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]);
    273286        usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n",
    274             data->tds[td_current].status, data->tds[td_current].cbp,
    275             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);
    276289}
    277290/*----------------------------------------------------------------------------*/
     
    279292{
    280293        assert(instance);
    281         ohci_batch_t *data = instance->private_data;
    282         assert(data);
    283         ed_init(data->ed, instance->ep);
    284         ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]);
    285         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,
    286297            data->ed->status, data->ed->td_tail, data->ed->td_head,
    287298            data->ed->next);
    288299
    289         /* data stage */
    290300        size_t td_current = 0;
    291301        size_t remain_size = instance->buffer_size;
    292         char *transfer_buffer = instance->transport_buffer;
     302        char *buffer = instance->data_buffer;
    293303        while (remain_size > 0) {
    294304                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
    295305                    OHCI_TD_MAX_TRANSFER : remain_size;
    296306
    297                 td_init(&data->tds[td_current], instance->ep->direction,
    298                     transfer_buffer, transfer_size, -1);
    299                 td_set_next(&data->tds[td_current], &data->tds[td_current + 1]);
     307                td_init(data->tds[td_current], instance->ep->direction,
     308                    buffer, transfer_size, -1);
     309                td_set_next(data->tds[td_current], data->tds[td_current + 1]);
    300310                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
    301                     data->tds[td_current].status, data->tds[td_current].cbp,
    302                     data->tds[td_current].next, data->tds[td_current].be);
    303 
    304                 transfer_buffer += transfer_size;
     311                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     312                    data->tds[td_current]->next, data->tds[td_current]->be);
     313
     314                buffer += transfer_size;
    305315                remain_size -= transfer_size;
    306316                assert(td_current < data->td_count);
     
    308318        }
    309319}
    310 /*----------------------------------------------------------------------------*/
    311 /** Helper function calls callback and correctly disposes of batch structure.
    312  *
    313  * @param[in] instance Batch structure to use.
    314  */
    315 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    316 {
    317         assert(instance);
    318         usb_transfer_batch_call_in(instance);
    319         batch_dispose(instance);
    320 }
    321 /*----------------------------------------------------------------------------*/
    322 /** Helper function calls callback and correctly disposes of batch structure.
    323  *
    324  * @param[in] instance Batch structure to use.
    325  */
    326 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    327 {
    328         assert(instance);
    329         usb_transfer_batch_call_out(instance);
    330         batch_dispose(instance);
    331 }
    332320/**
    333321 * @}
  • uspace/drv/ohci/batch.h

    r3f3afb9 ra39cfb8  
    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

    r3f3afb9 ra39cfb8  
    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

    r3f3afb9 ra39cfb8  
    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

    r3f3afb9 ra39cfb8  
    4343
    4444#include "hc.h"
     45#include "hcd_endpoint.h"
    4546
    4647static int interrupt_emulator(hc_t *instance);
     
    5556        assert(hub_fun);
    5657
     58        int ret;
     59
    5760        usb_address_t hub_address =
    5861            device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL);
     62        if (hub_address <= 0) {
     63                usb_log_error("Failed to get OHCI root hub address.\n");
     64                return hub_address;
     65        }
    5966        instance->rh.address = hub_address;
    6067        usb_device_keeper_bind(
    6168            &instance->manager, hub_address, hub_fun->handle);
    6269
    63         endpoint_t *ep = malloc(sizeof(endpoint_t));
    64         assert(ep);
    65         int ret = endpoint_init(ep, hub_address, 0, USB_DIRECTION_BOTH,
    66             USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64);
    67         assert(ret == EOK);
    68         ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, 0);
    69         assert(ret == EOK);
     70        ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
     71            USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
     72        if (ret != EOK) {
     73                usb_log_error("Failed to add OHCI rh endpoint 0.\n");
     74                usb_device_keeper_release(&instance->manager, hub_address);
     75                return ret;
     76        }
    7077
    7178        char *match_str = NULL;
     79        /* DDF needs heap allocated string */
    7280        ret = asprintf(&match_str, "usb&class=hub");
    73 //      ret = (match_str == NULL) ? ret : EOK;
    7481        if (ret < 0) {
    7582                usb_log_error(
    7683                    "Failed(%d) to create root hub match-id string.\n", ret);
     84                usb_device_keeper_release(&instance->manager, hub_address);
    7785                return ret;
    7886        }
     
    8088        ret = ddf_fun_add_match_id(hub_fun, match_str, 100);
    8189        if (ret != EOK) {
    82                 usb_log_error("Failed add create root hub match-id.\n");
     90                usb_log_error("Failed add root hub match-id.\n");
    8391        }
    8492        return ret;
     
    101109            ret, str_error(ret));
    102110
    103         instance->ddf_instance = fun;
    104111        usb_device_keeper_init(&instance->manager);
    105112        ret = usb_endpoint_manager_init(&instance->ep_manager,
     
    115122        fibril_mutex_initialize(&instance->guard);
    116123
    117         rh_init(&instance->rh, dev, instance->registers);
     124        rh_init(&instance->rh, instance->registers);
    118125
    119126        if (!interrupts) {
     
    123130        }
    124131
    125         return EOK;
    126 }
    127 /*----------------------------------------------------------------------------*/
    128 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
    129 {
    130         assert(instance);
    131         assert(batch);
    132 
    133         /* check for root hub communication */
    134         if (batch->target.address == instance->rh.address) {
    135                 return rh_request(&instance->rh, batch);
    136         }
    137 
    138         fibril_mutex_lock(&instance->guard);
    139         switch (batch->transfer_type) {
     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) {
    140167        case USB_TRANSFER_CONTROL:
    141168                instance->registers->control &= ~C_CLE;
    142                 transfer_list_add_batch(
    143                     instance->transfers[batch->transfer_type], batch);
    144                 instance->registers->command_status |= CS_CLF;
    145                 usb_log_debug2("Set CS control transfer filled: %x.\n",
    146                         instance->registers->command_status);
     169                endpoint_list_add_ep(
     170                    &instance->lists[ep->transfer_type], hcd_ep);
    147171                instance->registers->control_current = 0;
    148172                instance->registers->control |= C_CLE;
     
    150174        case USB_TRANSFER_BULK:
    151175                instance->registers->control &= ~C_BLE;
    152                 transfer_list_add_batch(
    153                     instance->transfers[batch->transfer_type], batch);
     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;
     253}
     254/*----------------------------------------------------------------------------*/
     255int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
     256{
     257        assert(instance);
     258        assert(batch);
     259        assert(batch->ep);
     260
     261        /* check for root hub communication */
     262        if (batch->ep->address == instance->rh.address) {
     263                return rh_request(&instance->rh, batch);
     264        }
     265
     266        fibril_mutex_lock(&instance->guard);
     267        list_append(&batch->link, &instance->pending_batches);
     268        batch_commit(batch);
     269        switch (batch->ep->transfer_type) {
     270        case USB_TRANSFER_CONTROL:
     271                instance->registers->command_status |= CS_CLF;
     272                break;
     273        case USB_TRANSFER_BULK:
    154274                instance->registers->command_status |= CS_BLF;
    155                 usb_log_debug2("Set bulk transfer filled: %x.\n",
    156                         instance->registers->command_status);
    157                 instance->registers->control |= C_BLE;
    158                 break;
    159         case USB_TRANSFER_INTERRUPT:
    160         case USB_TRANSFER_ISOCHRONOUS:
    161                 instance->registers->control &= (~C_PLE & ~C_IE);
    162                 transfer_list_add_batch(
    163                     instance->transfers[batch->transfer_type], batch);
    164                 instance->registers->control |= C_PLE | C_IE;
    165                 usb_log_debug2("Added periodic transfer: %x.\n",
    166                     instance->registers->periodic_current);
    167275                break;
    168276        default:
    169277                break;
    170278        }
     279
    171280        fibril_mutex_unlock(&instance->guard);
    172281        return EOK;
     
    189298                usb_log_debug2("Periodic current: %p.\n",
    190299                    instance->registers->periodic_current);
    191                 LIST_INITIALIZE(done);
    192                 transfer_list_remove_finished(
    193                     &instance->transfers_interrupt, &done);
    194                 transfer_list_remove_finished(
    195                     &instance->transfers_isochronous, &done);
    196                 transfer_list_remove_finished(
    197                     &instance->transfers_control, &done);
    198                 transfer_list_remove_finished(
    199                     &instance->transfers_bulk, &done);
    200 
    201                 while (!list_empty(&done)) {
    202                         link_t *item = done.next;
    203                         list_remove(item);
     300
     301                link_t *current = instance->pending_batches.next;
     302                while (current != &instance->pending_batches) {
     303                        link_t *next = current->next;
    204304                        usb_transfer_batch_t *batch =
    205                             list_get_instance(item, usb_transfer_batch_t, link);
    206                         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;
    207312                }
    208313                fibril_mutex_unlock(&instance->guard);
     
    298403
    299404        /* Use queues */
    300         instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
     405        instance->registers->bulk_head =
     406            instance->lists[USB_TRANSFER_BULK].list_head_pa;
    301407        usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
    302             instance->transfers_bulk.list_head,
    303             instance->transfers_bulk.list_head_pa);
     408            instance->lists[USB_TRANSFER_BULK].list_head,
     409            instance->lists[USB_TRANSFER_BULK].list_head_pa);
    304410
    305411        instance->registers->control_head =
    306             instance->transfers_control.list_head_pa;
     412            instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
    307413        usb_log_debug2("Control HEAD set to: %p(%p).\n",
    308             instance->transfers_control.list_head,
    309             instance->transfers_control.list_head_pa);
     414            instance->lists[USB_TRANSFER_CONTROL].list_head,
     415            instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
    310416
    311417        /* Enable queues */
     
    338444        assert(instance);
    339445
    340 #define SETUP_TRANSFER_LIST(type, name) \
     446#define SETUP_ENDPOINT_LIST(type) \
    341447do { \
    342         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); \
    343450        if (ret != EOK) { \
    344                 usb_log_error("Failed(%d) to setup %s transfer list.\n", \
     451                usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
    345452                    ret, name); \
    346                 transfer_list_fini(&instance->transfers_isochronous); \
    347                 transfer_list_fini(&instance->transfers_interrupt); \
    348                 transfer_list_fini(&instance->transfers_control); \
    349                 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]); \
    350457        } \
    351458} while (0)
    352459
    353         SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS");
    354         SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT");
    355         SETUP_TRANSFER_LIST(transfers_control, "CONTROL");
    356         SETUP_TRANSFER_LIST(transfers_bulk, "BULK");
    357 #undef SETUP_TRANSFER_LIST
    358         transfer_list_set_next(&instance->transfers_interrupt,
    359             &instance->transfers_isochronous);
    360 
    361         /* Assign pointers to be used during scheduling */
    362         instance->transfers[USB_TRANSFER_INTERRUPT] =
    363           &instance->transfers_interrupt;
    364         instance->transfers[USB_TRANSFER_ISOCHRONOUS] =
    365           &instance->transfers_interrupt;
    366         instance->transfers[USB_TRANSFER_CONTROL] =
    367           &instance->transfers_control;
    368         instance->transfers[USB_TRANSFER_BULK] =
    369           &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]);
    370467
    371468        return EOK;
     
    388485        for (; i < 32; ++i) {
    389486                instance->hcca->int_ep[i] =
    390                     instance->transfers_interrupt.list_head_pa;
     487                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
    391488        }
    392489        usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
    393             instance->transfers_interrupt.list_head,
    394             instance->transfers_interrupt.list_head_pa);
     490            instance->lists[USB_TRANSFER_INTERRUPT].list_head,
     491            instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
    395492
    396493        return EOK;
  • uspace/drv/ohci/hc.h

    r3f3afb9 ra39cfb8  
    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/hcd_endpoint.c

    r3f3afb9 ra39cfb8  
    11/*
    2  * Copyright (c) 2007 Jan Hudecek
    3  * Copyright (c) 2008 Martin Decky
     2 * Copyright (c) 2011 Jan Vesely
    43 * All rights reserved.
    54 *
     
    2726 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2827 */
    29 
    30 /** @addtogroup genericproc
     28/** @addtogroup drvusbohci
    3129 * @{
    3230 */
    33 /** @file tasklet.c
    34  *  @brief Tasklet implementation
     31/** @file
     32 * @brief OHCI driver
    3533 */
     34#include "utils/malloc32.h"
     35#include "hcd_endpoint.h"
    3636
    37 #include <proc/tasklet.h>
    38 #include <synch/spinlock.h>
    39 #include <mm/slab.h>
    40 #include <config.h>
     37hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep)
     38{
     39        assert(ep);
     40        hcd_endpoint_t *hcd_ep = malloc(sizeof(hcd_endpoint_t));
     41        if (hcd_ep == NULL)
     42                return NULL;
    4143
    42 /** Spinlock protecting list of tasklets */
    43 SPINLOCK_INITIALIZE(tasklet_lock);
     44        hcd_ep->ed = malloc32(sizeof(ed_t));
     45        if (hcd_ep->ed == NULL) {
     46                free(hcd_ep);
     47                return NULL;
     48        }
    4449
    45 /** Array of tasklet lists for every CPU */
    46 tasklet_descriptor_t **tasklet_list;
     50        hcd_ep->td = malloc32(sizeof(td_t));
     51        if (hcd_ep->td == NULL) {
     52                free32(hcd_ep->ed);
     53                free(hcd_ep);
     54                return NULL;
     55        }
    4756
    48 void tasklet_init(void)
     57        ed_init(hcd_ep->ed, ep);
     58        ed_set_td(hcd_ep->ed, hcd_ep->td);
     59        endpoint_set_hc_data(ep, hcd_ep, NULL, NULL);
     60
     61        return hcd_ep;
     62}
     63/*----------------------------------------------------------------------------*/
     64hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep)
    4965{
    50         unsigned int i;
    51        
    52         tasklet_list = malloc(sizeof(tasklet_descriptor_t *) * config.cpu_count, 0);
    53         if (!tasklet_list)
    54                 panic("Error initializing tasklets.");
    55        
    56         for (i = 0; i < config.cpu_count; i++)
    57                 tasklet_list[i] = NULL;
    58        
    59         spinlock_initialize(&tasklet_lock, "tasklet_lock");
     66        assert(ep);
     67        return ep->hc_data.data;
    6068}
    61 
    62 
    63 /** @}
     69/*----------------------------------------------------------------------------*/
     70void hcd_endpoint_clear(endpoint_t *ep)
     71{
     72        assert(ep);
     73        hcd_endpoint_t *hcd_ep = ep->hc_data.data;
     74        assert(hcd_ep);
     75        free32(hcd_ep->ed);
     76        free32(hcd_ep->td);
     77        free(hcd_ep);
     78}
     79/**
     80 * @}
    6481 */
  • uspace/drv/ohci/hcd_endpoint.h

    r3f3afb9 ra39cfb8  
    11/*
    2  * Copyright (c) 2007 Jan Hudecek
    3  * Copyright (c) 2008 Martin Decky
     2 * Copyright (c) 2011 Jan Vesely
    43 * All rights reserved.
    54 *
     
    2726 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2827 */
    29 
    30 /** @addtogroup genericproc
     28/** @addtogroup drvusbohci
    3129 * @{
    3230 */
    33 /** @file tasklet.h
    34  * @brief Tasklets declarations
     31/** @file
     32 * @brief OHCI driver
    3533 */
     34#ifndef DRV_OHCI_HCD_ENDPOINT_H
     35#define DRV_OHCI_HCD_ENDPOINT_H
    3636
    37 #ifndef KERN_TASKLET_H_
    38 #define KERN_TASKLET_H_
    39 
     37#include <assert.h>
    4038#include <adt/list.h>
    4139
    42 /** Tasklet callback type */
    43 typedef void (* tasklet_callback_t)(void *arg);
     40#include <usb/host/endpoint.h>
    4441
    45 /** Tasklet state */
    46 typedef enum {
    47         NotActive,
    48         Scheduled,
    49         InProgress,
    50         Disabled
    51 } tasklet_state_t;
     42#include "hw_struct/endpoint_descriptor.h"
     43#include "hw_struct/transfer_descriptor.h"
    5244
    53 /** Structure describing a tasklet */
    54 typedef struct tasklet_descriptor {
     45typedef struct hcd_endpoint {
     46        ed_t *ed;
     47        td_t *td;
    5548        link_t link;
    56        
    57         /** Callback to call */
    58         tasklet_callback_t callback;
    59        
    60         /** Argument passed to the callback */
    61         void *arg;
    62        
    63         /** State of the tasklet */
    64         tasklet_state_t state;
    65 } tasklet_descriptor_t;
     49} hcd_endpoint_t;
    6650
     51hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep);
    6752
    68 extern void tasklet_init(void);
     53hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep);
    6954
     55void hcd_endpoint_clear(endpoint_t *ep);
    7056#endif
    71 
    72 /** @}
     57/**
     58 * @}
    7359 */
  • uspace/drv/ohci/hw_struct/endpoint_descriptor.h

    r3f3afb9 ra39cfb8  
    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

    r3f3afb9 ra39cfb8  
    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/ohci/root_hub.c

    r3f3afb9 ra39cfb8  
    205205 * @return Error code.
    206206 */
    207 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs) {
     207int rh_init(rh_t *instance, ohci_regs_t *regs) {
    208208        assert(instance);
    209         //instance->address = -1;
    210209        instance->registers = regs;
    211         instance->device = dev;
    212210        instance->port_count =
    213211            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
    214212        rh_init_descriptors(instance);
    215213        // set port power mode to no-power-switching
    216         instance->registers->rh_desc_a =
    217                 instance->registers->rh_desc_a | (1<<9);
     214        instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
    218215
    219216        usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
    220 
    221         //start generic usb hub driver
    222 
    223         /* TODO: implement */
    224217        return EOK;
    225218}
     
    237230        assert(request);
    238231        int opResult;
    239         if (request->transfer_type == USB_TRANSFER_CONTROL) {
     232        if (request->ep->transfer_type == USB_TRANSFER_CONTROL) {
    240233                usb_log_info("Root hub got CONTROL packet\n");
    241234                opResult = process_ctrl_request(instance, request);
    242         } else if (request->transfer_type == USB_TRANSFER_INTERRUPT) {
     235        } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
    243236                usb_log_info("Root hub got INTERRUPT packet\n");
    244237                void * buffer;
    245238                create_interrupt_mask(instance, &buffer,
    246239                        &(request->transfered_size));
    247                 memcpy(request->transport_buffer, buffer,
     240                memcpy(request->data_buffer, buffer,
    248241                        request->transfered_size);
    249242                opResult = EOK;
     
    374367        if (port < 1 || port > instance->port_count)
    375368                return EINVAL;
    376         uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;
     369        uint32_t * uint32_buffer = (uint32_t*) request->data_buffer;
    377370        request->transfered_size = 4;
    378371        uint32_buffer[0] = instance->registers->rh_port_status[port - 1];
     
    400393static int process_get_hub_status_request(rh_t *instance,
    401394        usb_transfer_batch_t * request) {
    402         uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;
     395        uint32_t * uint32_buffer = (uint32_t*) request->data_buffer;
    403396        request->transfered_size = 4;
    404397        //bits, 0,1,16,17
     
    550543        }
    551544        request->transfered_size = size;
    552         memcpy(request->transport_buffer, result_descriptor, size);
     545        memcpy(request->data_buffer, result_descriptor, size);
    553546        if (del)
    554547                free(result_descriptor);
     
    571564        if (request->buffer_size != 1)
    572565                return EINVAL;
    573         request->transport_buffer[0] = 1;
     566        request->data_buffer[0] = 1;
    574567        request->transfered_size = 1;
    575568        return EOK;
  • uspace/drv/ohci/root_hub.h

    r3f3afb9 ra39cfb8  
    5050        /** usb address of the root hub */
    5151        usb_address_t address;
    52         /** ddf device information */
    53         ddf_dev_t *device;
    5452        /** hub port count */
    5553        int port_count;
     
    5856} rh_t;
    5957
    60 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs);
     58int rh_init(rh_t *instance, ohci_regs_t *regs);
    6159
    6260int rh_request(rh_t *instance, usb_transfer_batch_t *request);
  • uspace/drv/uhci-hcd/batch.c

    r3f3afb9 ra39cfb8  
    3030 */
    3131/** @file
    32  * @brief UHCI driver USB transaction structure
     32 * @brief UHCI driver USB transfer structure
    3333 */
    3434#include <errno.h>
     
    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         size_t transfers;
    51 } uhci_batch_t;
     50        void *device_buffer;
     51        size_t td_count;
     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.
    6168 *
    6269 * @param[in] fun DDF function to pass to callback.
    63  * @param[in] target Device and endpoint target of the transaction.
    64  * @param[in] transfer_type Interrupt, Control or Bulk.
    65  * @param[in] max_packet_size maximum allowed size of data transfers.
    66  * @param[in] speed Speed of the transaction.
     70 * @param[in] ep Communication target
    6771 * @param[in] buffer Data source/destination.
    6872 * @param[in] size Size of the buffer.
    6973 * @param[in] setup_buffer Setup data source (if not NULL)
    7074 * @param[in] setup_size Size of setup_buffer (should be always 8)
    71  * @param[in] func_in function to call on inbound transaction completion
    72  * @param[in] func_out function to call on outbound transaction completion
     75 * @param[in] func_in function to call on inbound transfer completion
     76 * @param[in] func_out function to call on outbound transfer completion
    7377 * @param[in] arg additional parameter to func_in or func_out
    74  * @param[in] ep Pointer to endpoint toggle management structure.
    75  * @return Valid pointer if all substructures were successfully created,
     78 * @return Valid pointer if all structures were successfully created,
    7679 * NULL otherwise.
    7780 *
    78  * Determines the number of needed transfers (TDs). Prepares a transport buffer
    79  * (that is accessible by the hardware). Initializes parameters needed for the
    80  * transaction and callback.
     81 * Determines the number of needed transfer descriptors (TDs).
     82 * Prepares a transport buffer (that is accessible by the hardware).
     83 * Initializes parameters needed for the transfer and callback.
    8184 */
    8285usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
     
    9295        if (ptr == NULL) { \
    9396                usb_log_error(message); \
    94                 if (instance) { \
    95                         batch_dispose(instance); \
     97                if (uhci_data) { \
     98                        uhci_transfer_batch_dispose(uhci_data); \
    9699                } \
    97100                return NULL; \
    98101        } else (void)0
    99102
     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, uhci_data->tds);
     129
    100130        usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
    101131        CHECK_NULL_DISPOSE_RETURN(instance,
    102132            "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;
    103137        usb_target_t target =
    104138            { .address = ep->address, .endpoint = ep->endpoint };
    105         usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed,
    106             ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
    107             func_in, func_out, arg, fun, ep, NULL);
    108 
    109 
    110         uhci_batch_t *data = malloc(sizeof(uhci_batch_t));
    111         CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
    112         bzero(data, sizeof(uhci_batch_t));
    113         instance->private_data = data;
    114 
    115         data->transfers =
    116             (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
    117         if (ep->transfer_type == USB_TRANSFER_CONTROL) {
    118                 data->transfers += 2;
    119         }
    120 
    121         data->tds = malloc32(sizeof(td_t) * data->transfers);
    122         CHECK_NULL_DISPOSE_RETURN(
    123             data->tds, "Failed to allocate transfer descriptors.\n");
    124         bzero(data->tds, sizeof(td_t) * data->transfers);
    125 
    126         data->qh = malloc32(sizeof(qh_t));
    127         CHECK_NULL_DISPOSE_RETURN(data->qh,
    128             "Failed to allocate batch queue head.\n");
    129         qh_init(data->qh);
    130         qh_set_element_td(data->qh, addr_to_phys(data->tds));
    131 
    132         if (buffer_size > 0) {
    133                 instance->transport_buffer = malloc32(buffer_size);
    134                 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
    135                     "Failed to allocate device accessible buffer.\n");
    136         }
    137 
    138         if (setup_size > 0) {
    139                 instance->setup_buffer = malloc32(setup_size);
    140                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    141                     "Failed to allocate device accessible setup buffer.\n");
    142                 memcpy(instance->setup_buffer, setup_buffer, setup_size);
    143         }
    144 
     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);
    145144        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
    146145            instance, target.address, target.endpoint);
     
    154153 *
    155154 * Walk all TDs. Stop with false if there is an active one (it is to be
    156  * processed). Stop with true if an error is found. Return true if the last TS
     155 * processed). Stop with true if an error is found. Return true if the last TD
    157156 * is reached.
    158157 */
     
    160159{
    161160        assert(instance);
    162         uhci_batch_t *data = instance->private_data;
     161        uhci_transfer_batch_t *data = instance->private_data;
    163162        assert(data);
    164163
    165164        usb_log_debug2("Batch(%p) checking %d transfer(s) for completion.\n",
    166             instance, data->transfers);
     165            instance, data->td_count);
    167166        instance->transfered_size = 0;
    168167        size_t i = 0;
    169         for (;i < data->transfers; ++i) {
     168        for (;i < data->td_count; ++i) {
    170169                if (td_is_active(&data->tds[i])) {
    171170                        return false;
     
    177176                            instance, i, data->tds[i].status);
    178177                        td_print_status(&data->tds[i]);
     178
    179179                        assert(instance->ep != NULL);
    180 
    181180                        endpoint_toggle_set(instance->ep,
    182181                            td_toggle(&data->tds[i]));
     
    195194}
    196195/*----------------------------------------------------------------------------*/
    197 /** Prepares control write transaction.
    198  *
    199  * @param[in] instance Batch structure to use.
    200  *
    201  * Uses genercir control function with pids OUT and IN.
     196/** Prepares control write transfer.
     197 *
     198 * @param[in] instance Batch structure to use.
     199 *
     200 * Uses generic control function with pids OUT and IN.
    202201 */
    203202void batch_control_write(usb_transfer_batch_t *instance)
     
    205204        assert(instance);
    206205        /* We are data out, we are supposed to provide data */
    207         memcpy(instance->transport_buffer, instance->buffer,
    208             instance->buffer_size);
     206        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    209207        batch_control(instance, USB_PID_OUT, USB_PID_IN);
    210         instance->next_step = batch_call_out_and_dispose;
     208        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    211209        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    212210}
    213211/*----------------------------------------------------------------------------*/
    214 /** Prepares control read transaction.
     212/** Prepares control read transfer.
    215213 *
    216214 * @param[in] instance Batch structure to use.
     
    222220        assert(instance);
    223221        batch_control(instance, USB_PID_IN, USB_PID_OUT);
    224         instance->next_step = batch_call_in_and_dispose;
     222        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    225223        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    226224}
    227225/*----------------------------------------------------------------------------*/
    228 /** Prepare interrupt in transaction.
    229  *
    230  * @param[in] instance Batch structure to use.
    231  *
    232  * Data transaction with PID_IN.
     226/** Prepare interrupt in transfer.
     227 *
     228 * @param[in] instance Batch structure to use.
     229 *
     230 * Data transfer with PID_IN.
    233231 */
    234232void batch_interrupt_in(usb_transfer_batch_t *instance)
    235233{
    236234        assert(instance);
    237         instance->direction = USB_DIRECTION_IN;
    238235        batch_data(instance, USB_PID_IN);
    239         instance->next_step = batch_call_in_and_dispose;
     236        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    240237        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    241238}
    242239/*----------------------------------------------------------------------------*/
    243 /** Prepare interrupt out transaction.
    244  *
    245  * @param[in] instance Batch structure to use.
    246  *
    247  * Data transaction with PID_OUT.
     240/** Prepare interrupt out transfer.
     241 *
     242 * @param[in] instance Batch structure to use.
     243 *
     244 * Data transfer with PID_OUT.
    248245 */
    249246void batch_interrupt_out(usb_transfer_batch_t *instance)
    250247{
    251248        assert(instance);
    252         instance->direction = USB_DIRECTION_OUT;
    253249        /* We are data out, we are supposed to provide data */
    254         memcpy(instance->transport_buffer, instance->buffer,
    255             instance->buffer_size);
     250        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    256251        batch_data(instance, USB_PID_OUT);
    257         instance->next_step = batch_call_out_and_dispose;
     252        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    258253        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    259254}
    260255/*----------------------------------------------------------------------------*/
    261 /** Prepare bulk in transaction.
    262  *
    263  * @param[in] instance Batch structure to use.
    264  *
    265  * Data transaction with PID_IN.
     256/** Prepare bulk in transfer.
     257 *
     258 * @param[in] instance Batch structure to use.
     259 *
     260 * Data transfer with PID_IN.
    266261 */
    267262void batch_bulk_in(usb_transfer_batch_t *instance)
     
    269264        assert(instance);
    270265        batch_data(instance, USB_PID_IN);
    271         instance->direction = USB_DIRECTION_IN;
    272         instance->next_step = batch_call_in_and_dispose;
     266        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    273267        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    274268}
    275269/*----------------------------------------------------------------------------*/
    276 /** Prepare bulk out transaction.
    277  *
    278  * @param[in] instance Batch structure to use.
    279  *
    280  * Data transaction with PID_OUT.
     270/** Prepare bulk out transfer.
     271 *
     272 * @param[in] instance Batch structure to use.
     273 *
     274 * Data transfer with PID_OUT.
    281275 */
    282276void batch_bulk_out(usb_transfer_batch_t *instance)
    283277{
    284278        assert(instance);
    285         instance->direction = USB_DIRECTION_OUT;
    286279        /* We are data out, we are supposed to provide data */
    287         memcpy(instance->transport_buffer, instance->buffer,
    288             instance->buffer_size);
     280        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    289281        batch_data(instance, USB_PID_OUT);
    290         instance->next_step = batch_call_out_and_dispose;
     282        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    291283        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
    292284}
    293285/*----------------------------------------------------------------------------*/
    294 /** Prepare generic data transaction
    295  *
    296  * @param[in] instance Batch structure to use.
    297  * @param[in] pid Pid to use for data transfers.
    298  *
    299  * Packets with alternating toggle bit and supplied pid value.
     286/** Prepare generic data transfer
     287 *
     288 * @param[in] instance Batch structure to use.
     289 * @param[in] pid Pid to use for data transactions.
     290 *
     291 * Transactions with alternating toggle bit and supplied pid value.
    300292 * The last transfer is marked with IOC flag.
    301293 */
     
    303295{
    304296        assert(instance);
    305         uhci_batch_t *data = instance->private_data;
     297        uhci_transfer_batch_t *data = instance->private_data;
    306298        assert(data);
    307299
    308         const bool low_speed = instance->speed == USB_SPEED_LOW;
     300        const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
    309301        int toggle = endpoint_toggle_get(instance->ep);
    310302        assert(toggle == 0 || toggle == 1);
    311303
    312         size_t transfer = 0;
     304        size_t td = 0;
    313305        size_t remain_size = instance->buffer_size;
     306        char *buffer = instance->data_buffer;
    314307        while (remain_size > 0) {
    315                 char *trans_data =
    316                     instance->transport_buffer + instance->buffer_size
    317                     - remain_size;
    318 
    319308                const size_t packet_size =
    320                     (instance->max_packet_size > remain_size) ?
    321                     remain_size : instance->max_packet_size;
    322 
    323                 td_t *next_transfer = (transfer + 1 < data->transfers)
    324                     ? &data->tds[transfer + 1] : NULL;
    325 
    326                 assert(transfer < data->transfers);
     309                    (instance->ep->max_packet_size > remain_size) ?
     310                    remain_size : instance->ep->max_packet_size;
     311
     312                td_t *next_td = (td + 1 < data->td_count)
     313                    ? &data->tds[td + 1] : NULL;
     314
     315
     316                usb_target_t target =
     317                    { instance->ep->address, instance->ep->endpoint };
     318
     319                assert(td < data->td_count);
     320                td_init(
     321                    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
     322                    toggle, false, low_speed, target, pid, buffer, next_td);
     323
     324                ++td;
     325                toggle = 1 - toggle;
     326                buffer += packet_size;
    327327                assert(packet_size <= remain_size);
    328 
    329                 td_init(
    330                     &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size,
    331                     toggle, false, low_speed, instance->target, pid, trans_data,
    332                     next_transfer);
    333 
    334 
    335                 toggle = 1 - toggle;
    336328                remain_size -= packet_size;
    337                 ++transfer;
    338329        }
    339         td_set_ioc(&data->tds[transfer - 1]);
     330        td_set_ioc(&data->tds[td - 1]);
    340331        endpoint_toggle_set(instance->ep, toggle);
    341332}
    342333/*----------------------------------------------------------------------------*/
    343 /** Prepare generic control transaction
    344  *
    345  * @param[in] instance Batch structure to use.
    346  * @param[in] data_stage Pid to use for data transfers.
    347  * @param[in] status_stage Pid to use for data transfers.
     334/** Prepare generic control transfer
     335 *
     336 * @param[in] instance Batch structure to use.
     337 * @param[in] data_stage Pid to use for data tds.
     338 * @param[in] status_stage Pid to use for data tds.
    348339 *
    349340 * Setup stage with toggle 0 and USB_PID_SETUP.
     
    356347{
    357348        assert(instance);
    358         uhci_batch_t *data = instance->private_data;
     349        uhci_transfer_batch_t *data = instance->private_data;
    359350        assert(data);
    360         assert(data->transfers >= 2);
    361 
    362         const bool low_speed = instance->speed == USB_SPEED_LOW;
    363         int toggle = 0;
     351        assert(data->td_count >= 2);
     352
     353        const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
     354        const usb_target_t target =
     355            { instance->ep->address, instance->ep->endpoint };
     356
    364357        /* setup stage */
    365358        td_init(
    366             data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, toggle, false,
    367             low_speed, instance->target, USB_PID_SETUP, instance->setup_buffer,
     359            data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, 0, false,
     360            low_speed, target, USB_PID_SETUP, instance->setup_buffer,
    368361            &data->tds[1]);
    369362
    370363        /* data stage */
    371         size_t transfer = 1;
     364        size_t td = 1;
     365        unsigned toggle = 1;
    372366        size_t remain_size = instance->buffer_size;
     367        char *buffer = instance->data_buffer;
    373368        while (remain_size > 0) {
    374                 char *control_data =
    375                     instance->transport_buffer + instance->buffer_size
    376                     - remain_size;
    377 
     369                const size_t packet_size =
     370                    (instance->ep->max_packet_size > remain_size) ?
     371                    remain_size : instance->ep->max_packet_size;
     372
     373                td_init(
     374                    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
     375                    toggle, false, low_speed, target, data_stage,
     376                    buffer, &data->tds[td + 1]);
     377
     378                ++td;
    378379                toggle = 1 - toggle;
    379 
    380                 const size_t packet_size =
    381                     (instance->max_packet_size > remain_size) ?
    382                     remain_size : instance->max_packet_size;
    383 
    384                 td_init(
    385                     &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size,
    386                     toggle, false, low_speed, instance->target, data_stage,
    387                     control_data, &data->tds[transfer + 1]);
    388 
    389                 ++transfer;
    390                 assert(transfer < data->transfers);
     380                buffer += packet_size;
     381                assert(td < data->td_count);
    391382                assert(packet_size <= remain_size);
    392383                remain_size -= packet_size;
     
    394385
    395386        /* status stage */
    396         assert(transfer == data->transfers - 1);
     387        assert(td == data->td_count - 1);
    397388
    398389        td_init(
    399             &data->tds[transfer], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
    400             instance->target, status_stage, NULL, NULL);
    401         td_set_ioc(&data->tds[transfer]);
     390            &data->tds[td], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
     391            target, status_stage, NULL, NULL);
     392        td_set_ioc(&data->tds[td]);
    402393
    403394        usb_log_debug2("Control last TD status: %x.\n",
    404             data->tds[transfer].status);
    405 }
    406 /*----------------------------------------------------------------------------*/
     395            data->tds[td].status);
     396}
     397/*----------------------------------------------------------------------------*/
     398/** Provides access to QH data structure.
     399 * @param[in] instance Batch pointer to use.
     400 * @return Pointer to the QH used by the batch.
     401 */
    407402qh_t * batch_qh(usb_transfer_batch_t *instance)
    408403{
    409404        assert(instance);
    410         uhci_batch_t *data = instance->private_data;
     405        uhci_transfer_batch_t *data = instance->private_data;
    411406        assert(data);
    412407        return data->qh;
    413408}
    414 /*----------------------------------------------------------------------------*/
    415 /** Helper function calls callback and correctly disposes of batch structure.
    416  *
    417  * @param[in] instance Batch structure to use.
    418  */
    419 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    420 {
    421         assert(instance);
    422         usb_transfer_batch_call_in(instance);
    423         batch_dispose(instance);
    424 }
    425 /*----------------------------------------------------------------------------*/
    426 /** Helper function calls callback and correctly disposes of batch structure.
    427  *
    428  * @param[in] instance Batch structure to use.
    429  */
    430 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    431 {
    432         assert(instance);
    433         usb_transfer_batch_call_out(instance);
    434         batch_dispose(instance);
    435 }
    436 /*----------------------------------------------------------------------------*/
    437 /** Correctly dispose all used data structures.
    438  *
    439  * @param[in] instance Batch structure to use.
    440  */
    441 void batch_dispose(usb_transfer_batch_t *instance)
    442 {
    443         assert(instance);
    444         uhci_batch_t *data = instance->private_data;
    445         assert(data);
    446         usb_log_debug("Batch(%p) disposing.\n", instance);
    447         /* free32 is NULL safe */
    448         free32(data->tds);
    449         free32(data->qh);
    450         free32(instance->setup_buffer);
    451         free32(instance->transport_buffer);
    452         free(data);
    453         free(instance);
    454 }
    455409/**
    456410 * @}
  • uspace/drv/uhci-hcd/batch.h

    r3f3afb9 ra39cfb8  
    3030 */
    3131/** @file
    32  * @brief UHCI driver USB transaction structure
     32 * @brief UHCI driver USB tranfer helper functions
    3333 */
    3434#ifndef DRV_UHCI_BATCH_H
  • uspace/drv/uhci-hcd/hc.c

    r3f3afb9 ra39cfb8  
    6666static int hc_interrupt_emulator(void *arg);
    6767static int hc_debug_checker(void *arg);
    68 #if 0
    69 static bool usb_is_allowed(
    70     bool low_speed, usb_transfer_type_t transfer, size_t size);
    71 #endif
    7268/*----------------------------------------------------------------------------*/
    7369/** Initialize UHCI hcd driver structure
     
    8985        int ret;
    9086
    91 #define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
     87#define CHECK_RET_RETURN(ret, message...) \
    9288        if (ret != EOK) { \
    9389                usb_log_error(message); \
    94                 if (instance->ddf_instance) \
    95                         ddf_fun_destroy(instance->ddf_instance); \
    9690                return ret; \
    9791        } else (void) 0
     
    9993        instance->hw_interrupts = interrupts;
    10094        instance->hw_failures = 0;
    101 
    102         /* Setup UHCI function. */
    103         instance->ddf_instance = fun;
    10495
    10596        /* allow access to hc control registers */
    10697        regs_t *io;
    10798        ret = pio_enable(regs, reg_size, (void**)&io);
    108         CHECK_RET_DEST_FUN_RETURN(ret,
     99        CHECK_RET_RETURN(ret,
    109100            "Failed(%d) to gain access to registers at %p: %s.\n",
    110             ret, str_error(ret), io);
     101            ret, io, str_error(ret));
    111102        instance->registers = io;
    112103        usb_log_debug("Device registers at %p(%u) accessible.\n",
     
    114105
    115106        ret = hc_init_mem_structures(instance);
    116         CHECK_RET_DEST_FUN_RETURN(ret,
    117             "Failed to initialize UHCI memory structures.\n");
     107        CHECK_RET_RETURN(ret,
     108            "Failed(%d) to initialize UHCI memory structures: %s.\n",
     109            ret, str_error(ret));
    118110
    119111        hc_init_hw(instance);
    120112        if (!interrupts) {
    121                 instance->cleaner =
     113                instance->interrupt_emulator =
    122114                    fibril_create(hc_interrupt_emulator, instance);
    123                 fibril_add_ready(instance->cleaner);
    124         } else {
    125                 /* TODO: enable interrupts here */
    126         }
    127 
    128         instance->debug_checker =
    129             fibril_create(hc_debug_checker, instance);
    130 //      fibril_add_ready(instance->debug_checker);
     115                fibril_add_ready(instance->interrupt_emulator);
     116        }
     117        (void)hc_debug_checker;
    131118
    132119        return EOK;
     
    228215        /* Set all frames to point to the first queue head */
    229216        const uint32_t queue =
    230           instance->transfers_interrupt.queue_head_pa
    231           | LINK_POINTER_QUEUE_HEAD_FLAG;
     217            LINK_POINTER_QH(addr_to_phys(
     218                instance->transfers_interrupt.queue_head));
    232219
    233220        unsigned i = 0;
     
    236223        }
    237224
    238         /* Init device keeper*/
     225        /* Init device keeper */
    239226        usb_device_keeper_init(&instance->manager);
    240227        usb_log_debug("Initialized device manager.\n");
     
    329316
    330317        transfer_list_t *list =
    331             instance->transfers[batch->speed][batch->transfer_type];
     318            instance->transfers[batch->ep->speed][batch->ep->transfer_type];
    332319        assert(list);
    333320        transfer_list_add_batch(list, batch);
     
    479466#undef QH
    480467}
    481 /*----------------------------------------------------------------------------*/
    482 /** Check transfers for USB validity
    483  *
    484  * @param[in] low_speed Transfer speed.
    485  * @param[in] transfer Transer type
    486  * @param[in] size Size of data packets
    487  * @return True if transaction is allowed by USB specs, false otherwise
    488  */
    489 #if 0
    490 bool usb_is_allowed(
    491     bool low_speed, usb_transfer_type_t transfer, size_t size)
    492 {
    493         /* see USB specification chapter 5.5-5.8 for magic numbers used here */
    494         switch(transfer)
    495         {
    496         case USB_TRANSFER_ISOCHRONOUS:
    497                 return (!low_speed && size < 1024);
    498         case USB_TRANSFER_INTERRUPT:
    499                 return size <= (low_speed ? 8 : 64);
    500         case USB_TRANSFER_CONTROL: /* device specifies its own max size */
    501                 return (size <= (low_speed ? 8 : 64));
    502         case USB_TRANSFER_BULK: /* device specifies its own max size */
    503                 return (!low_speed && size <= 64);
    504         }
    505         return false;
    506 }
    507 #endif
    508468/**
    509469 * @}
  • uspace/drv/uhci-hcd/hc.h

    r3f3afb9 ra39cfb8  
    4848#include "transfer_list.h"
    4949
     50/** UHCI I/O registers layout */
    5051typedef struct uhci_regs {
     52        /** Command register, controls HC behaviour */
    5153        uint16_t usbcmd;
    5254#define UHCI_CMD_MAX_PACKET (1 << 7)
     
    5961#define UHCI_CMD_RUN_STOP  (1 << 0)
    6062
     63        /** Status register, 1 means interrupt is asserted (if enabled) */
    6164        uint16_t usbsts;
    6265#define UHCI_STATUS_HALTED (1 << 5)
     
    6770#define UHCI_STATUS_INTERRUPT (1 << 0)
    6871
     72        /** Interrupt enabled registers */
    6973        uint16_t usbintr;
    7074#define UHCI_INTR_SHORT_PACKET (1 << 3)
     
    7377#define UHCI_INTR_CRC (1 << 0)
    7478
     79        /** Register stores frame number used in SOF packet */
    7580        uint16_t frnum;
     81
     82        /** Pointer(physical) to the Frame List */
    7683        uint32_t flbaseadd;
     84
     85        /** SOF modification to match external timers */
    7786        uint8_t sofmod;
    7887} regs_t;
     
    8392#define UHCI_ALLOWED_HW_FAIL 5
    8493
     94/* Main HC driver structure */
    8595typedef struct hc {
     96        /** USB bus driver, devices and addresses */
    8697        usb_device_keeper_t manager;
     98        /** USB bus driver, endpoints */
    8799        usb_endpoint_manager_t ep_manager;
    88100
     101        /** Addresses of I/O registers */
    89102        regs_t *registers;
    90103
     104        /** Frame List contains 1024 link pointers */
    91105        link_pointer_t *frame_list;
    92106
     107        /** List and queue of interrupt transfers */
     108        transfer_list_t transfers_interrupt;
     109        /** List and queue of low speed control transfers */
     110        transfer_list_t transfers_control_slow;
     111        /** List and queue of full speed bulk transfers */
    93112        transfer_list_t transfers_bulk_full;
     113        /** List and queue of full speed control transfers */
    94114        transfer_list_t transfers_control_full;
    95         transfer_list_t transfers_control_slow;
    96         transfer_list_t transfers_interrupt;
    97115
     116        /** Pointer table to the above lists, helps during scheduling */
    98117        transfer_list_t *transfers[2][4];
    99118
     119        /** Code to be executed in kernel interrupt handler */
    100120        irq_code_t interrupt_code;
    101121
    102         fid_t cleaner;
    103         fid_t debug_checker;
     122        /** Fibril periodically checking status register*/
     123        fid_t interrupt_emulator;
     124
     125        /** Indicator of hw interrupts availability */
    104126        bool hw_interrupts;
     127
     128        /** Number of hw failures detected. */
    105129        unsigned hw_failures;
    106 
    107         ddf_fun_t *ddf_instance;
    108130} hc_t;
    109131
  • uspace/drv/uhci-hcd/hw_struct/queue_head.h

    r3f3afb9 ra39cfb8  
    3434#ifndef DRV_UHCI_QH_H
    3535#define DRV_UHCI_QH_H
    36 
    37 /* libc */
    3836#include <assert.h>
    3937
    4038#include "link_pointer.h"
     39#include "transfer_descriptor.h"
     40#include "utils/malloc32.h"
    4141
     42/** This structure is defined in UHCI design guide p. 31 */
    4243typedef struct queue_head {
     44        /** Pointer to the next entity (another QH or TD */
    4345        volatile link_pointer_t next;
     46        /** Pointer to the contained entities (execution controlled by vertical flag*/
    4447        volatile link_pointer_t element;
    4548} __attribute__((packed)) qh_t;
     
    6467 * @param[in] pa Physical address of the next queue head.
    6568 *
    66  * Adds proper flag. If the pointer is NULL or terminal, sets next to terminal
    67  * NULL.
     69 * Adds proper flag. If the pointer is NULL, sets next to terminal NULL.
    6870 */
    69 static inline void qh_set_next_qh(qh_t *instance, uint32_t pa)
     71static inline void qh_set_next_qh(qh_t *instance, qh_t *next)
    7072{
    71         /* Address is valid and not terminal */
    72         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
     73        uint32_t pa = addr_to_phys(next);
     74        if (pa) {
    7375                instance->next = LINK_POINTER_QH(pa);
    7476        } else {
     
    8082 *
    8183 * @param[in] instance qh_t structure to initialize.
    82  * @param[in] pa Physical address of the next queue head.
    83  *
    84  * Adds proper flag. If the pointer is NULL or terminal, sets element
    85  * to terminal NULL.
    86  */
    87 static inline void qh_set_element_qh(qh_t *instance, uint32_t pa)
    88 {
    89         /* Address is valid and not terminal */
    90         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
    91                 instance->element = LINK_POINTER_QH(pa);
    92         } else {
    93                 instance->element = LINK_POINTER_TERM;
    94         }
    95 }
    96 /*----------------------------------------------------------------------------*/
    97 /** Set queue head element pointer
    98  *
    99  * @param[in] instance qh_t structure to initialize.
    10084 * @param[in] pa Physical address of the TD structure.
    10185 *
    102  * Adds proper flag. If the pointer is NULL or terminal, sets element
    103  * to terminal NULL.
     86 * Adds proper flag. If the pointer is NULL, sets element to terminal NULL.
    10487 */
    105 static inline void qh_set_element_td(qh_t *instance, uint32_t pa)
     88static inline void qh_set_element_td(qh_t *instance, td_t *td)
    10689{
    107         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
     90        uint32_t pa = addr_to_phys(td);
     91        if (pa) {
    10892                instance->element = LINK_POINTER_TD(pa);
    10993        } else {
     
    11195        }
    11296}
    113 
    11497#endif
    11598/**
  • uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c

    r3f3afb9 ra39cfb8  
    7777
    7878        instance->status = 0
    79             | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
     79            | ((err_count & TD_STATUS_ERROR_COUNT_MASK)
     80                << TD_STATUS_ERROR_COUNT_POS)
    8081            | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
    8182            | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0)
     
    8990            | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
    9091            | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
    91             | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
    92             | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
     92            | ((target.address & TD_DEVICE_ADDRESS_MASK)
     93                << TD_DEVICE_ADDRESS_POS)
     94            | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK)
     95                << TD_DEVICE_ENDPOINT_POS)
    9396            | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
    9497
     
    114117        assert(instance);
    115118
    116         /* this is hc internal error it should never be reported */
     119        /* This is hc internal error it should never be reported. */
    117120        if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
    118121                return EAGAIN;
     
    123126                return EBADCHECKSUM;
    124127
    125         /* hc does not end transaction on these, it should never be reported */
     128        /* HC does not end transactions on these, it should never be reported */
    126129        if ((instance->status & TD_STATUS_ERROR_NAK) != 0)
    127130                return EAGAIN;
    128131
    129         /* buffer overrun or underrun */
     132        /* Buffer overrun or underrun */
    130133        if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0)
    131134                return ERANGE;
    132135
    133         /* device babble is something serious */
     136        /* Device babble is something serious */
    134137        if ((instance->status & TD_STATUS_ERROR_BABBLE) != 0)
    135138                return EIO;
    136139
    137         /* stall might represent err count reaching zero or stall response from
    138          * the device, is err count reached zero, one of the above is reported*/
     140        /* Stall might represent err count reaching zero or stall response from
     141         * the device. If err count reached zero, one of the above is reported*/
    139142        if ((instance->status & TD_STATUS_ERROR_STALLED) != 0)
    140143                return ESTALL;
  • uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.h

    r3f3afb9 ra39cfb8  
    4040#include "link_pointer.h"
    4141
    42 /** UHCI Transfer Descriptor */
     42/** Transfer Descriptor, defined in UHCI design guide p. 26 */
    4343typedef struct transfer_descriptor {
     44        /** Pointer to the next entity (TD or QH) */
    4445        link_pointer_t next;
    4546
     47        /** Status doubleword */
    4648        volatile uint32_t status;
    4749#define TD_STATUS_RESERVED_MASK 0xc000f800
    48 #define TD_STATUS_SPD_FLAG ( 1 << 29 )
    49 #define TD_STATUS_ERROR_COUNT_POS ( 27 )
    50 #define TD_STATUS_ERROR_COUNT_MASK ( 0x3 )
    51 #define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 )
    52 #define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 )
    53 #define TD_STATUS_IOC_FLAG ( 1 << 24 )
     50#define TD_STATUS_SPD_FLAG         (1 << 29)
     51#define TD_STATUS_ERROR_COUNT_POS 27
     52#define TD_STATUS_ERROR_COUNT_MASK 0x3
     53#define TD_STATUS_LOW_SPEED_FLAG   (1 << 26)
     54#define TD_STATUS_ISOCHRONOUS_FLAG (1 << 25)
     55#define TD_STATUS_IOC_FLAG         (1 << 24)
    5456
    55 #define TD_STATUS_ERROR_ACTIVE ( 1 << 23 )
    56 #define TD_STATUS_ERROR_STALLED ( 1 << 22 )
    57 #define TD_STATUS_ERROR_BUFFER ( 1 << 21 )
    58 #define TD_STATUS_ERROR_BABBLE ( 1 << 20 )
    59 #define TD_STATUS_ERROR_NAK ( 1 << 19 )
    60 #define TD_STATUS_ERROR_CRC ( 1 << 18 )
    61 #define TD_STATUS_ERROR_BIT_STUFF ( 1 << 17 )
    62 #define TD_STATUS_ERROR_RESERVED ( 1 << 16 )
     57#define TD_STATUS_ERROR_ACTIVE    (1 << 23)
     58#define TD_STATUS_ERROR_STALLED   (1 << 22)
     59#define TD_STATUS_ERROR_BUFFER    (1 << 21)
     60#define TD_STATUS_ERROR_BABBLE    (1 << 20)
     61#define TD_STATUS_ERROR_NAK       (1 << 19)
     62#define TD_STATUS_ERROR_CRC       (1 << 18)
     63#define TD_STATUS_ERROR_BIT_STUFF (1 << 17)
     64#define TD_STATUS_ERROR_RESERVED  (1 << 16)
    6365#define TD_STATUS_ERROR_POS 16
    64 #define TD_STATUS_ERROR_MASK ( 0xff )
     66#define TD_STATUS_ERROR_MASK 0xff
    6567
    6668#define TD_STATUS_ACTLEN_POS 0
    6769#define TD_STATUS_ACTLEN_MASK 0x7ff
    6870
     71        /* double word with USB device specific info */
    6972        volatile uint32_t device;
    7073#define TD_DEVICE_MAXLEN_POS 21
    71 #define TD_DEVICE_MAXLEN_MASK ( 0x7ff )
    72 #define TD_DEVICE_RESERVED_FLAG ( 1 << 20 )
    73 #define TD_DEVICE_DATA_TOGGLE_ONE_FLAG ( 1 << 19 )
     74#define TD_DEVICE_MAXLEN_MASK 0x7ff
     75#define TD_DEVICE_RESERVED_FLAG        (1 << 20)
     76#define TD_DEVICE_DATA_TOGGLE_ONE_FLAG (1 << 19)
    7477#define TD_DEVICE_ENDPOINT_POS 15
    75 #define TD_DEVICE_ENDPOINT_MASK ( 0xf )
     78#define TD_DEVICE_ENDPOINT_MASK 0xf
    7679#define TD_DEVICE_ADDRESS_POS 8
    77 #define TD_DEVICE_ADDRESS_MASK ( 0x7f )
     80#define TD_DEVICE_ADDRESS_MASK 0x7f
    7881#define TD_DEVICE_PID_POS 0
    79 #define TD_DEVICE_PID_MASK ( 0xff )
     82#define TD_DEVICE_PID_MASK 0xff
    8083
     84        /** Pointer(physical) to the beginning of the transaction's buffer */
    8185        volatile uint32_t buffer_ptr;
    8286
    83         /* there is 16 bytes of data available here, according to UHCI
    84          * Design guide, according to linux kernel the hardware does not care,
    85          * it just needs to be aligned, we don't use it anyway
     87        /* According to UHCI design guide, there is 16 bytes of
     88         * data available here.
     89         * According to linux kernel the hardware does not care,
     90         * it just needs to be aligned. We don't use it anyway.
    8691         */
    8792} __attribute__((packed)) td_t;
  • uspace/drv/uhci-hcd/iface.c

    r3f3afb9 ra39cfb8  
    148148        assert(hc);
    149149        const size_t size = max_packet_size;
    150         int ret;
    151150        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
    152151        if (speed >= USB_SPEED_MAX) {
     
    157156            usb_str_speed(speed), direction, size, max_packet_size, interval);
    158157
    159 
    160         endpoint_t *ep = malloc(sizeof(endpoint_t));
    161         if (ep == NULL)
    162                 return ENOMEM;
    163         ret = endpoint_init(ep, address, endpoint, direction,
    164             transfer_type, speed, max_packet_size);
    165         if (ret != EOK) {
    166                 free(ep);
    167                 return ret;
    168         }
    169 
    170         ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
    171         if (ret != EOK) {
    172                 endpoint_destroy(ep);
    173         }
    174         return ret;
     158        return usb_endpoint_manager_add_ep(&hc->ep_manager, address, endpoint,
     159            direction, transfer_type, speed, max_packet_size, size);
    175160}
    176161/*----------------------------------------------------------------------------*/
     
    210195        ret = hc_schedule(hc, batch);
    211196        if (ret != EOK) {
    212                 batch_dispose(batch);
     197                usb_transfer_batch_dispose(batch);
    213198        }
    214199        return ret;
     
    238223        ret = hc_schedule(hc, batch);
    239224        if (ret != EOK) {
    240                 batch_dispose(batch);
     225                usb_transfer_batch_dispose(batch);
    241226        }
    242227        return ret;
     
    266251        ret = hc_schedule(hc, batch);
    267252        if (ret != EOK) {
    268                 batch_dispose(batch);
     253                usb_transfer_batch_dispose(batch);
    269254        }
    270255        return ret;
     
    294279        ret = hc_schedule(hc, batch);
    295280        if (ret != EOK) {
    296                 batch_dispose(batch);
     281                usb_transfer_batch_dispose(batch);
    297282        }
    298283        return ret;
     
    327312        ret = hc_schedule(hc, batch);
    328313        if (ret != EOK) {
    329                 batch_dispose(batch);
     314                usb_transfer_batch_dispose(batch);
    330315        }
    331316        return ret;
     
    359344        ret = hc_schedule(hc, batch);
    360345        if (ret != EOK) {
    361                 batch_dispose(batch);
     346                usb_transfer_batch_dispose(batch);
    362347        }
    363348        return ret;
  • uspace/drv/uhci-hcd/main.c

    r3f3afb9 ra39cfb8  
    3939#include <usb/debug.h>
    4040
    41 #include "iface.h"
    4241#include "uhci.h"
    4342
     
    6261int uhci_add_device(ddf_dev_t *device)
    6362{
    64         usb_log_debug("uhci_add_device() called\n");
     63        usb_log_debug2("uhci_add_device() called\n");
    6564        assert(device);
     65
    6666        uhci_t *uhci = malloc(sizeof(uhci_t));
    6767        if (uhci == NULL) {
     
    7272        int ret = uhci_init(uhci, device);
    7373        if (ret != EOK) {
    74                 usb_log_error("Failed to initialize UHCI driver: %s.\n",
    75                     str_error(ret));
     74                usb_log_error("Failed(%d) to initialize UHCI driver: %s.\n",
     75                    ret, str_error(ret));
    7676                return ret;
    7777        }
     
    8585/** Initialize global driver structures (NONE).
    8686 *
    87  * @param[in] argc Nmber of arguments in argv vector (ignored).
     87 * @param[in] argc Number of arguments in argv vector (ignored).
    8888 * @param[in] argv Cmdline argument vector (ignored).
    8989 * @return Error code.
     
    9494{
    9595        printf(NAME ": HelenOS UHCI driver.\n");
    96 
    97         sleep(3); /* TODO: remove in final version */
    9896        usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
    9997
  • uspace/drv/uhci-hcd/pci.c

    r3f3afb9 ra39cfb8  
    4444#include "pci.h"
    4545
    46 /** Get address of registers and IRQ for given device.
     46/** Get I/O address of registers and IRQ for given device.
    4747 *
    4848 * @param[in] dev Device asking for the addresses.
     
    5353 */
    5454int pci_get_my_registers(ddf_dev_t *dev,
    55     uintptr_t *io_reg_address, size_t *io_reg_size,
    56     int *irq_no)
     55    uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no)
    5756{
    5857        assert(dev != NULL);
    5958
    60         int parent_phone = devman_parent_device_connect(dev->handle,
    61             IPC_FLAG_BLOCKING);
     59        int parent_phone =
     60            devman_parent_device_connect(dev->handle, IPC_FLAG_BLOCKING);
    6261        if (parent_phone < 0) {
    6362                return parent_phone;
    6463        }
    6564
    66         int rc;
    6765        hw_resource_list_t hw_resources;
    68         rc = hw_res_get_resource_list(parent_phone, &hw_resources);
     66        int rc = hw_res_get_resource_list(parent_phone, &hw_resources);
    6967        if (rc != EOK) {
    7068                goto leave;
     
    9593                            res->res.io_range.address, res->res.io_range.size);
    9694                        io_found = true;
     95                        break;
    9796
    9897                default:
     
    113112leave:
    114113        async_hangup(parent_phone);
    115 
    116114        return rc;
    117115}
     
    145143        }
    146144
    147         /* See UHCI design guide for these values,
     145        /* See UHCI design guide for these values p.45,
    148146         * write all WC bits in USB legacy register */
    149147        sysarg_t address = 0xc0;
  • uspace/drv/uhci-hcd/root_hub.c

    r3f3afb9 ra39cfb8  
    5555        int ret = asprintf(&match_str, "usb&uhci&root-hub");
    5656        if (ret < 0) {
    57                 usb_log_error("Failed to create root hub match string.\n");
    58                 return ENOMEM;
     57                usb_log_error(
     58                    "Failed(%d) to create root hub match string: %s.\n",
     59                    ret, str_error(ret));
     60                return ret;
    5961        }
    6062
    6163        ret = ddf_fun_add_match_id(fun, match_str, 100);
    6264        if (ret != EOK) {
     65                free(match_str);
    6366                usb_log_error("Failed(%d) to add root hub match id: %s\n",
    6467                    ret, str_error(ret));
     
    6669        }
    6770
    68         hw_resource_list_t *resource_list = &instance->resource_list;
    69         resource_list->count = 1;
    70         resource_list->resources = &instance->io_regs;
    71         assert(resource_list->resources);
     71        /* Initialize resource structure */
     72        instance->resource_list.count = 1;
     73        instance->resource_list.resources = &instance->io_regs;
     74
    7275        instance->io_regs.type = IO_RANGE;
    7376        instance->io_regs.res.io_range.address = reg_addr;
  • uspace/drv/uhci-hcd/root_hub.h

    r3f3afb9 ra39cfb8  
    3939#include <ops/hw_res.h>
    4040
     41/** DDF support structure for uhci-rhd driver, provides I/O resources */
    4142typedef struct rh {
     43        /** List of resources available to the root hub. */
    4244        hw_resource_list_t resource_list;
     45        /** The only resource in the above list */
    4346        hw_resource_t io_regs;
    4447} rh_t;
  • uspace/drv/uhci-hcd/transfer_list.c

    r3f3afb9 ra39cfb8  
    5757                return ENOMEM;
    5858        }
    59         instance->queue_head_pa = addr_to_phys(instance->queue_head);
     59        uint32_t queue_head_pa = addr_to_phys(instance->queue_head);
    6060        usb_log_debug2("Transfer list %s setup with QH: %p(%p).\n",
    61             name, instance->queue_head, instance->queue_head_pa);
     61            name, instance->queue_head, queue_head_pa);
    6262
    6363        qh_init(instance->queue_head);
     
    6767}
    6868/*----------------------------------------------------------------------------*/
     69/** Dispose transfer list structures.
     70 *
     71 * @param[in] instance Memory place to use.
     72 *
     73 * Frees memory for internal qh_t structure.
     74 */
     75void transfer_list_fini(transfer_list_t *instance)
     76{
     77        assert(instance);
     78        free32(instance->queue_head);
     79}
    6980/** Set the next list in transfer list chain.
    7081 *
     
    8192        if (!instance->queue_head)
    8293                return;
    83         /* Set both queue_head.next to point to the follower */
    84         qh_set_next_qh(instance->queue_head, next->queue_head_pa);
    85 }
    86 /*----------------------------------------------------------------------------*/
    87 /** Submit transfer batch to the list and queue.
     94        /* Set queue_head.next to point to the follower */
     95        qh_set_next_qh(instance->queue_head, next->queue_head);
     96}
     97/*----------------------------------------------------------------------------*/
     98/** Add transfer batch to the list and queue.
    8899 *
    89100 * @param[in] instance List to use.
    90101 * @param[in] batch Transfer batch to submit.
    91  * @return Error code
    92102 *
    93103 * The batch is added to the end of the list and queue.
     
    109119        } else {
    110120                /* There is something scheduled */
    111                 usb_transfer_batch_t *last = list_get_instance(
    112                     instance->batch_list.prev, usb_transfer_batch_t, link);
     121                usb_transfer_batch_t *last =
     122                    usb_transfer_batch_from_link(instance->batch_list.prev);
    113123                last_qh = batch_qh(last);
    114124        }
     
    118128        /* keep link */
    119129        batch_qh(batch)->next = last_qh->next;
    120         qh_set_next_qh(last_qh, pa);
     130        qh_set_next_qh(last_qh, batch_qh(batch));
    121131
    122132        asm volatile ("": : :"memory");
     
    132142}
    133143/*----------------------------------------------------------------------------*/
    134 /** Create list for finished batches.
     144/** Add completed bantches to the provided list.
    135145 *
    136146 * @param[in] instance List to use.
     
    147157                link_t *next = current->next;
    148158                usb_transfer_batch_t *batch =
    149                     list_get_instance(current, usb_transfer_batch_t, link);
     159                    usb_transfer_batch_from_link(current);
    150160
    151161                if (batch_is_complete(batch)) {
    152                         /* Save for post-processing */
     162                        /* Save for processing */
    153163                        transfer_list_remove_batch(instance, batch);
    154164                        list_append(current, done);
     
    159169}
    160170/*----------------------------------------------------------------------------*/
    161 /** Walk the list and abort all batches.
     171/** Walk the list and finish all batches with EINTR.
    162172 *
    163173 * @param[in] instance List to use.
     
    169179                link_t *current = instance->batch_list.next;
    170180                usb_transfer_batch_t *batch =
    171                     list_get_instance(current, usb_transfer_batch_t, link);
     181                    usb_transfer_batch_from_link(current);
    172182                transfer_list_remove_batch(instance, batch);
    173                 usb_transfer_batch_finish_error(batch, EIO);
     183                usb_transfer_batch_finish_error(batch, EINTR);
    174184        }
    175185        fibril_mutex_unlock(&instance->guard);
     
    180190 * @param[in] instance List to use.
    181191 * @param[in] batch Transfer batch to remove.
    182  * @return Error code
    183192 *
    184193 * Does not lock the transfer list, caller is responsible for that.
     
    197206
    198207        const char *qpos = NULL;
     208        qh_t *prev_qh = NULL;
    199209        /* Remove from the hardware queue */
    200210        if (instance->batch_list.next == &batch->link) {
    201211                /* I'm the first one here */
    202                 assert((instance->queue_head->next & LINK_POINTER_ADDRESS_MASK)
    203                     == addr_to_phys(batch_qh(batch)));
    204                 instance->queue_head->next = batch_qh(batch)->next;
     212                prev_qh = instance->queue_head;
    205213                qpos = "FIRST";
    206214        } else {
     215                /* The thing before me is a batch too */
    207216                usb_transfer_batch_t *prev =
    208                     list_get_instance(
    209                         batch->link.prev, usb_transfer_batch_t, link);
    210                 assert((batch_qh(prev)->next & LINK_POINTER_ADDRESS_MASK)
    211                     == addr_to_phys(batch_qh(batch)));
    212                 batch_qh(prev)->next = batch_qh(batch)->next;
     217                    usb_transfer_batch_from_link(batch->link.prev);
     218                prev_qh = batch_qh(prev);
    213219                qpos = "NOT FIRST";
    214220        }
     221        assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK)
     222            == addr_to_phys(batch_qh(batch)));
     223        prev_qh->next = batch_qh(batch)->next;
    215224        asm volatile ("": : :"memory");
    216225        /* Remove from the batch list */
    217226        list_remove(&batch->link);
    218         usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n",
     227        usb_log_debug("Batch(%p) removed (%s) from %s, next: %x.\n",
    219228            batch, qpos, instance->name, batch_qh(batch)->next);
    220229}
  • uspace/drv/uhci-hcd/transfer_list.h

    r3f3afb9 ra39cfb8  
    3939#include "batch.h"
    4040#include "hw_struct/queue_head.h"
    41 #include "utils/malloc32.h"
    4241
     42/** Structure maintaining both hw queue and software list
     43 * of currently executed transfers
     44 */
    4345typedef struct transfer_list
    4446{
     47        /** Guard against multiple add/remove races */
    4548        fibril_mutex_t guard;
     49        /** UHCI hw structure represeting this queue */
    4650        qh_t *queue_head;
    47         uint32_t queue_head_pa;
     51        /** Assigned name, for nicer debug output */
    4852        const char *name;
     53        /** List of all batches in this list */
    4954        link_t batch_list;
    5055} transfer_list_t;
    5156
    52 /** Dispose transfer list structures.
    53  *
    54  * @param[in] instance Memory place to use.
    55  *
    56  * Frees memory for internal qh_t structure.
    57  */
    58 static inline void transfer_list_fini(transfer_list_t *instance)
    59 {
    60         assert(instance);
    61         free32(instance->queue_head);
    62 }
    63 
     57void transfer_list_fini(transfer_list_t *instance);
    6458int transfer_list_init(transfer_list_t *instance, const char *name);
    65 
    6659void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
    67 
    68 void transfer_list_add_batch(transfer_list_t *instance, usb_transfer_batch_t *batch);
    69 
     60void transfer_list_add_batch(
     61    transfer_list_t *instance, usb_transfer_batch_t *batch);
    7062void transfer_list_remove_finished(transfer_list_t *instance, link_t *done);
    71 
    7263void transfer_list_abort_all(transfer_list_t *instance);
    7364#endif
  • uspace/drv/uhci-hcd/uhci.c

    r3f3afb9 ra39cfb8  
    4444#include "pci.h"
    4545
    46 /** IRQ handling callback, identifies device
     46/** IRQ handling callback, forward status from call to diver structure.
    4747 *
    4848 * @param[in] dev DDF instance of the device to use.
    4949 * @param[in] iid (Unused).
    50  * @param[in] call Pointer to the call that represents interrupt.
     50 * @param[in] call Pointer to the call from kernel.
    5151 */
    5252static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
     
    6161/** Get address of the device identified by handle.
    6262 *
    63  * @param[in] dev DDF instance of the device to use.
    64  * @param[in] iid (Unused).
    65  * @param[in] call Pointer to the call that represents interrupt.
     63 * @param[in] fun DDF instance of the function to use.
     64 * @param[in] handle DDF handle of the driver seeking its USB address.
     65 * @param[out] address Found address.
    6666 */
    6767static int usb_iface_get_address(
     
    6969{
    7070        assert(fun);
    71         usb_device_keeper_t *manager = &((uhci_t*)fun->dev->driver_data)->hc.manager;
     71        usb_device_keeper_t *manager =
     72            &((uhci_t*)fun->dev->driver_data)->hc.manager;
    7273
    7374        usb_address_t addr = usb_device_keeper_find(manager, handle);
     
    8384}
    8485/*----------------------------------------------------------------------------*/
    85 /** Gets handle of the respective hc (this or parent device).
    86  *
    87  * @param[in] root_hub_fun Root hub function seeking hc handle.
    88  * @param[out] handle Place to write the handle.
     86/** Gets handle of the respective hc.
     87 *
     88 * @param[in] fun DDF function of uhci device.
     89 * @param[out] handle Host cotnroller handle.
    8990 * @return Error code.
    9091 */
     
    100101}
    101102/*----------------------------------------------------------------------------*/
    102 /** This iface is generic for both RH and HC. */
     103/** USB interface implementation used by RH */
    103104static usb_iface_t usb_iface = {
    104105        .get_hc_handle = usb_iface_get_hc_handle,
     
    106107};
    107108/*----------------------------------------------------------------------------*/
     109/** Operations supported by the HC driver */
    108110static ddf_dev_ops_t hc_ops = {
    109 //      .interfaces[USB_DEV_IFACE] = &usb_iface,
    110111        .interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
    111112};
     
    122123}
    123124/*----------------------------------------------------------------------------*/
     125/** Interface to provide the root hub driver with hw info */
    124126static hw_res_ops_t hw_res_iface = {
    125127        .get_resource_list = get_resource_list,
     
    127129};
    128130/*----------------------------------------------------------------------------*/
     131/** RH function support for uhci-rhd */
    129132static ddf_dev_ops_t rh_ops = {
    130133        .interfaces[USB_DEV_IFACE] = &usb_iface,
     
    132135};
    133136/*----------------------------------------------------------------------------*/
    134 /** Initialize hc and rh ddf structures and their respective drivers.
     137/** Initialize hc and rh DDF structures and their respective drivers.
    135138 *
    136139 * @param[in] instance UHCI structure to use.
     
    138141 *
    139142 * This function does all the preparatory work for hc and rh drivers:
    140  *  - gets device hw resources
    141  *  - disables UHCI legacy support
     143 *  - gets device's hw resources
     144 *  - disables UHCI legacy support (PCI config space)
    142145 *  - asks for interrupt
    143146 *  - registers interrupt handler
     
    193196        ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
    194197        CHECK_RET_DEST_FUN_RETURN(ret,
    195             "Failed(%d) to create HC function.\n", ret);
     198            "Failed(%d) to create HC function: %s.\n", ret, str_error(ret));
    196199
    197200        ret = hc_init(&instance->hc, instance->hc_fun,
    198201            (void*)io_reg_base, io_reg_size, interrupts);
    199         CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret);
     202        CHECK_RET_DEST_FUN_RETURN(ret,
     203            "Failed(%d) to init uhci-hcd: %s.\n", ret, str_error(ret));
     204
    200205        instance->hc_fun->ops = &hc_ops;
    201206        instance->hc_fun->driver_data = &instance->hc;
     
    221226            &instance->hc.interrupt_code);
    222227        CHECK_RET_FINI_RETURN(ret,
    223             "Failed(%d) to register interrupt handler.\n", ret);
     228            "Failed(%d) to register interrupt handler: %s.\n",
     229            ret, str_error(ret));
    224230
    225231        instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh");
    226232        ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
    227233        CHECK_RET_FINI_RETURN(ret,
    228             "Failed(%d) to create root hub function.\n", ret);
     234            "Failed(%d) to create root hub function: %s.\n",
     235            ret, str_error(ret));
    229236
    230237        ret = rh_init(&instance->rh, instance->rh_fun,
    231238            (uintptr_t)instance->hc.registers + 0x10, 4);
    232239        CHECK_RET_FINI_RETURN(ret,
    233             "Failed(%d) to setup UHCI root hub.\n", ret);
     240            "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(ret));
    234241
    235242        instance->rh_fun->ops = &rh_ops;
     
    237244        ret = ddf_fun_bind(instance->rh_fun);
    238245        CHECK_RET_FINI_RETURN(ret,
    239             "Failed(%d) to register UHCI root hub.\n", ret);
     246            "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
    240247
    241248        return EOK;
  • uspace/drv/uhci-hcd/uhci.h

    r3f3afb9 ra39cfb8  
    4141#include "root_hub.h"
    4242
     43/** Structure representing both functions of UHCI hc, USB host controller
     44 * and USB root hub */
    4345typedef struct uhci {
     46        /** Pointer to DDF represenation of UHCI host controller */
    4447        ddf_fun_t *hc_fun;
     48        /** Pointer to DDF represenation of UHCI root hub */
    4549        ddf_fun_t *rh_fun;
    4650
     51        /** Internal driver's represenation of UHCI host controller */
    4752        hc_t hc;
     53        /** Internal driver's represenation of UHCI root hub */
    4854        rh_t rh;
    4955} uhci_t;
    5056
    5157int uhci_init(uhci_t *instance, ddf_dev_t *device);
    52 
    5358#endif
    5459/**
Note: See TracChangeset for help on using the changeset viewer.