Changeset d8b275d in mainline for uspace/drv


Ignore:
Timestamp:
2011-04-14T08:24:29Z (15 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5e07e2b5
Parents:
3f2af64 (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 development/ changes

Location:
uspace/drv
Files:
4 added
46 edited
4 moved

Legend:

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

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

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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);
    53 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    54 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    55 
    56 #define DEFAULT_ERROR_COUNT 3
     73static void batch_data(usb_transfer_batch_t *instance);
     74/*----------------------------------------------------------------------------*/
    5775usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
    5876    char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
     
    6482                usb_log_error(message); \
    6583                if (instance) { \
    66                         batch_dispose(instance); \
     84                        usb_transfer_batch_dispose(instance); \
    6785                } \
    6886                return NULL; \
     
    7290        CHECK_NULL_DISPOSE_RETURN(instance,
    7391            "Failed to allocate batch instance.\n");
    74         usb_target_t target =
    75             { .address = ep->address, .endpoint = ep->endpoint };
    76         usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed,
    77             ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
    78             func_in, func_out, arg, fun, ep, NULL);
    79 
    80         ohci_batch_t *data = malloc(sizeof(ohci_batch_t));
     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);
    81100        CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
    82         bzero(data, sizeof(ohci_batch_t));
    83101        instance->private_data = data;
    84102
    85         /* we needs + 1 transfer descriptor as the last one won't be executed */
    86         data->td_count = 1 +
     103        data->td_count =
    87104            ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
    88105        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     
    90107        }
    91108
    92         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);
    93111        CHECK_NULL_DISPOSE_RETURN(data->tds,
    94112            "Failed to allocate transfer descriptors.\n");
    95         bzero(data->tds, sizeof(td_t) * data->td_count);
    96 
    97         data->ed = malloc32(sizeof(ed_t));
    98         CHECK_NULL_DISPOSE_RETURN(data->ed,
    99             "Failed to allocate endpoint descriptor.\n");
    100 
    101         if (buffer_size > 0) {
    102                 instance->transport_buffer = malloc32(buffer_size);
    103                 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,
    104128                    "Failed to allocate device accessible buffer.\n");
    105         }
    106 
    107         if (setup_size > 0) {
    108                 instance->setup_buffer = malloc32(setup_size);
    109                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    110                     "Failed to allocate device accessible setup buffer.\n");
     129                instance->setup_buffer = data->device_buffer;
     130                instance->data_buffer = data->device_buffer + setup_size;
    111131                memcpy(instance->setup_buffer, setup_buffer, setup_size);
    112132        }
     
    115135}
    116136/*----------------------------------------------------------------------------*/
    117 void batch_dispose(usb_transfer_batch_t *instance)
    118 {
    119         assert(instance);
    120         ohci_batch_t *data = instance->private_data;
    121         assert(data);
    122         free32(data->ed);
    123         free32(data->tds);
    124         free32(instance->setup_buffer);
    125         free32(instance->transport_buffer);
    126         free(data);
    127         free(instance);
    128 }
    129 /*----------------------------------------------------------------------------*/
    130137bool batch_is_complete(usb_transfer_batch_t *instance)
    131138{
    132139        assert(instance);
    133         ohci_batch_t *data = instance->private_data;
    134         assert(data);
    135         size_t tds = data->td_count - 1;
    136         usb_log_debug2("Batch(%p) checking %d td(s) for completion.\n",
     140        ohci_transfer_batch_t *data = instance->private_data;
     141        assert(data);
     142        size_t tds = data->td_count;
     143        usb_log_debug("Batch(%p) checking %d td(s) for completion.\n",
    137144            instance, tds);
     145        usb_log_debug("ED: %x:%x:%x:%x.\n",
     146            data->ed->status, data->ed->td_head, data->ed->td_tail,
     147            data->ed->next);
    138148        size_t i = 0;
    139149        for (; i < tds; ++i) {
    140                 if (!td_is_finished(&data->tds[i]))
     150                assert(data->tds[i] != NULL);
     151                usb_log_debug("TD %d: %x:%x:%x:%x.\n", 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])) {
    141155                        return false;
    142                 instance->error = td_error(&data->tds[i]);
     156                }
     157                instance->error = td_error(data->tds[i]);
    143158                /* FIXME: calculate real transfered size */
    144159                instance->transfered_size = instance->buffer_size;
    145160                if (instance->error != EOK) {
    146161                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
    147                             instance, i, data->tds[i].status);
    148                         return true;
    149 //                      endpoint_toggle_set(instance->ep,
     162                            instance, i, data->tds[i]->status);
     163                        break;
    150164                }
    151165        }
     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
    152172        return true;
    153173}
    154174/*----------------------------------------------------------------------------*/
     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/*----------------------------------------------------------------------------*/
    155183void batch_control_write(usb_transfer_batch_t *instance)
    156184{
    157185        assert(instance);
    158186        /* We are data out, we are supposed to provide data */
    159         memcpy(instance->transport_buffer, instance->buffer,
    160             instance->buffer_size);
    161         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;
    162189        batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
    163190        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
     
    167194{
    168195        assert(instance);
    169         instance->next_step = batch_call_in_and_dispose;
     196        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    170197        batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
    171198        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
     
    175202{
    176203        assert(instance);
    177         assert(instance->direction == USB_DIRECTION_IN);
    178         instance->next_step = batch_call_in_and_dispose;
    179         /* TODO: implement */
     204        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     205        batch_data(instance);
    180206        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    181207}
     
    184210{
    185211        assert(instance);
    186         assert(instance->direction == USB_DIRECTION_OUT);
    187212        /* We are data out, we are supposed to provide data */
    188         memcpy(instance->transport_buffer, instance->buffer,
    189             instance->buffer_size);
    190         instance->next_step = batch_call_out_and_dispose;
    191         /* TODO: implement */
     213        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     214        instance->next_step = usb_transfer_batch_call_out_and_dispose;
     215        batch_data(instance);
    192216        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    193217}
     
    196220{
    197221        assert(instance);
    198         instance->direction = USB_DIRECTION_IN;
    199         instance->next_step = batch_call_in_and_dispose;
    200         /* TODO: implement */
     222        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     223        batch_data(instance);
    201224        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    202225}
     
    205228{
    206229        assert(instance);
    207         instance->direction = USB_DIRECTION_IN;
    208         instance->next_step = batch_call_in_and_dispose;
    209         /* TODO: implement */
     230        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     231        batch_data(instance);
    210232        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    211233}
     
    214236{
    215237        assert(instance);
    216         ohci_batch_t *data = instance->private_data;
     238        ohci_transfer_batch_t *data = instance->private_data;
    217239        assert(data);
    218240        return data->ed;
     
    223245{
    224246        assert(instance);
    225         ohci_batch_t *data = instance->private_data;
    226         assert(data);
    227         ed_init(data->ed, instance->ep);
    228         ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]);
    229         usb_log_debug("Created ED(%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,
    230250            data->ed->status, data->ed->td_tail, data->ed->td_head,
    231251            data->ed->next);
    232252        int toggle = 0;
    233253        /* setup stage */
    234         td_init(&data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
     254        td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
    235255                instance->setup_size, toggle);
    236         td_set_next(&data->tds[0], &data->tds[1]);
    237         usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0].status,
    238             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);
    239259
    240260        /* data stage */
    241261        size_t td_current = 1;
    242262        size_t remain_size = instance->buffer_size;
    243         char *transfer_buffer = instance->transport_buffer;
     263        char *buffer = instance->data_buffer;
    244264        while (remain_size > 0) {
    245265                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     
    247267                toggle = 1 - toggle;
    248268
    249                 td_init(&data->tds[td_current], data_dir, transfer_buffer,
     269                td_init(data->tds[td_current], data_dir, buffer,
    250270                    transfer_size, toggle);
    251                 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]);
    252272                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
    253                     data->tds[td_current].status, data->tds[td_current].cbp,
    254                     data->tds[td_current].next, data->tds[td_current].be);
    255 
    256                 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;
    257277                remain_size -= transfer_size;
    258                 assert(td_current < data->td_count - 2);
     278                assert(td_current < data->td_count - 1);
    259279                ++td_current;
    260280        }
    261281
    262282        /* status stage */
    263         assert(td_current == data->td_count - 2);
    264         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]);
    265286        usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n",
    266             data->tds[td_current].status, data->tds[td_current].cbp,
    267             data->tds[td_current].next, data->tds[td_current].be);
    268 }
    269 /*----------------------------------------------------------------------------*/
    270 /** Helper function calls callback and correctly disposes of batch structure.
    271  *
    272  * @param[in] instance Batch structure to use.
    273  */
    274 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    275 {
    276         assert(instance);
    277         usb_transfer_batch_call_in(instance);
    278         batch_dispose(instance);
    279 }
    280 /*----------------------------------------------------------------------------*/
    281 /** Helper function calls callback and correctly disposes of batch structure.
    282  *
    283  * @param[in] instance Batch structure to use.
    284  */
    285 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    286 {
    287         assert(instance);
    288         usb_transfer_batch_call_out(instance);
    289         batch_dispose(instance);
     287            data->tds[td_current]->status, data->tds[td_current]->cbp,
     288            data->tds[td_current]->next, data->tds[td_current]->be);
     289}
     290/*----------------------------------------------------------------------------*/
     291void batch_data(usb_transfer_batch_t *instance)
     292{
     293        assert(instance);
     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,
     297            data->ed->status, data->ed->td_tail, data->ed->td_head,
     298            data->ed->next);
     299
     300        size_t td_current = 0;
     301        size_t remain_size = instance->buffer_size;
     302        char *buffer = instance->data_buffer;
     303        while (remain_size > 0) {
     304                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     305                    OHCI_TD_MAX_TRANSFER : remain_size;
     306
     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]);
     310                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
     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;
     315                remain_size -= transfer_size;
     316                assert(td_current < data->td_count);
     317                ++td_current;
     318        }
    290319}
    291320/**
  • uspace/drv/ohci/batch.h

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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);
    8077        assert(next);
    81         /* Set both queue_head.next to point to the follower */
    8278        ed_append_ed(instance->list_head, next->list_head);
    8379}
    8480/*----------------------------------------------------------------------------*/
    85 /** Submit transfer batch to the list and queue.
    86  *
    87  * @param[in] instance List to use.
    88  * @param[in] batch Transfer batch to submit.
    89  * @return Error code
    90  *
    91  * The batch is added to the end of the list and queue.
    92  */
    93 void transfer_list_add_batch(
    94     transfer_list_t *instance, usb_transfer_batch_t *batch)
    95 {
    96         assert(instance);
    97         assert(batch);
    98         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);
    9995
    10096        fibril_mutex_lock(&instance->guard);
     
    10298        ed_t *last_ed = NULL;
    10399        /* Add to the hardware queue. */
    104         if (list_empty(&instance->batch_list)) {
     100        if (list_empty(&instance->endpoint_list)) {
    105101                /* There is nothing scheduled */
    106102                last_ed = instance->list_head;
    107103        } else {
    108104                /* There is something scheduled */
    109                 usb_transfer_batch_t *last = list_get_instance(
    110                     instance->batch_list.prev, usb_transfer_batch_t, link);
    111                 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;
    112108        }
    113109        /* keep link */
    114         batch_ed(batch)->next = last_ed->next;
    115         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);
    116112
    117113        asm volatile ("": : :"memory");
    118114
    119115        /* Add to the driver list */
    120         list_append(&batch->link, &instance->batch_list);
    121 
    122         usb_transfer_batch_t *first = list_get_instance(
    123             instance->batch_list.next, usb_transfer_batch_t, link);
    124         usb_log_debug("Batch(%p) added to list %s, first is %p(%p).\n",
    125                 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);
    126122        if (last_ed == instance->list_head) {
    127                 usb_log_debug2("%s head ED: %x:%x:%x:%x.\n", instance->name,
    128                         last_ed->status, last_ed->td_tail, last_ed->td_head,
    129                         last_ed->next);
    130         }
    131         fibril_mutex_unlock(&instance->guard);
    132 }
    133 /*----------------------------------------------------------------------------*/
    134 /** Create list for finished batches.
     123                usb_log_debug2("%s head ED(%p-%p): %x:%x:%x:%x.\n",
     124                    instance->name, last_ed, instance->list_head_pa,
     125                    last_ed->status, last_ed->td_tail, last_ed->td_head,
     126                    last_ed->next);
     127        }
     128        fibril_mutex_unlock(&instance->guard);
     129}
     130/*----------------------------------------------------------------------------*/
     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         link_t *current = instance->batch_list.next;
    146         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) {
    147147                link_t *next = current->next;
    148                 usb_transfer_batch_t *batch =
    149                     list_get_instance(current, usb_transfer_batch_t, link);
    150 
    151                 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)) {
    152152                        /* Save for post-processing */
    153                         transfer_list_remove_batch(instance, batch);
     153                        endpoint_list_remove_endpoint(instance, endpoint);
    154154                        list_append(current, done);
    155155                }
     
    159159}
    160160/*----------------------------------------------------------------------------*/
    161 /** Walk the list and abort all batches.
    162  *
    163  * @param[in] instance List to use.
    164  */
    165 void transfer_list_abort_all(transfer_list_t *instance)
    166 {
    167         fibril_mutex_lock(&instance->guard);
    168         while (!list_empty(&instance->batch_list)) {
    169                 link_t *current = instance->batch_list.next;
    170                 usb_transfer_batch_t *batch =
    171                     list_get_instance(current, usb_transfer_batch_t, link);
    172                 transfer_list_remove_batch(instance, batch);
    173                 usb_transfer_batch_finish_error(batch, EIO);
    174         }
    175         fibril_mutex_unlock(&instance->guard);
    176 }
    177 /*----------------------------------------------------------------------------*/
    178 /** Remove a transfer batch from the list and queue.
    179  *
    180  * @param[in] instance List to use.
    181  * @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.
    182183 * @return Error code
    183184 *
    184185 * Does not lock the transfer list, caller is responsible for that.
    185186 */
    186 void transfer_list_remove_batch(
    187     transfer_list_t *instance, usb_transfer_batch_t *batch)
     187void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
    188188{
    189189        assert(instance);
    190190        assert(instance->list_head);
    191         assert(batch);
    192         assert(batch_ed(batch));
    193         assert(fibril_mutex_is_locked(&instance->guard));
     191        assert(hcd_ep);
     192        assert(hcd_ep->ed);
     193
     194        fibril_mutex_lock(&instance->guard);
    194195
    195196        usb_log_debug2(
    196             "Queue %s: removing batch(%p).\n", instance->name, batch);
     197            "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep);
    197198
    198199        const char *qpos = NULL;
     200        ed_t *prev_ed;
    199201        /* Remove from the hardware queue */
    200         if (instance->batch_list.next == &batch->link) {
     202        if (instance->endpoint_list.next == &hcd_ep->link) {
    201203                /* I'm the first one here */
    202                 assert((instance->list_head->next & ED_NEXT_PTR_MASK)
    203                     == addr_to_phys(batch_ed(batch)));
    204                 instance->list_head->next = batch_ed(batch)->next;
     204                prev_ed = instance->list_head;
    205205                qpos = "FIRST";
    206206        } else {
    207                 usb_transfer_batch_t *prev =
    208                     list_get_instance(
    209                         batch->link.prev, usb_transfer_batch_t, link);
    210                 assert((batch_ed(prev)->next & ED_NEXT_PTR_MASK)
    211                     == addr_to_phys(batch_ed(batch)));
    212                 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;
    213210                qpos = "NOT FIRST";
    214211        }
     212        assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed));
     213        prev_ed->next = hcd_ep->ed->next;
     214
    215215        asm volatile ("": : :"memory");
    216         usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n",
    217             batch, qpos, instance->name, batch_ed(batch)->next);
    218 
    219         /* Remove from the batch list */
    220         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);
    221222}
    222223/**
  • uspace/drv/ohci/endpoint_list.h

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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,
     
    113120            ret, str_error(ret));
    114121        hc_init_hw(instance);
    115 
    116         rh_init(&instance->rh, dev, instance->registers);
     122        fibril_mutex_initialize(&instance->guard);
     123
     124        rh_init(&instance->rh, instance->registers);
    117125
    118126        if (!interrupts) {
     
    122130        }
    123131
    124         return EOK;
    125 }
    126 /*----------------------------------------------------------------------------*/
    127 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
    128 {
    129         assert(instance);
    130         assert(batch);
    131 
    132         /* check for root hub communication */
    133         if (batch->target.address == instance->rh.address) {
    134                 return rh_request(&instance->rh, batch);
    135         }
    136 
    137         transfer_list_add_batch(
    138             instance->transfers[batch->transfer_type], batch);
    139 
    140         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) {
    141167        case USB_TRANSFER_CONTROL:
    142168                instance->registers->control &= ~C_CLE;
     169                endpoint_list_add_ep(
     170                    &instance->lists[ep->transfer_type], hcd_ep);
     171                instance->registers->control_current = 0;
     172                instance->registers->control |= C_CLE;
     173                break;
     174        case USB_TRANSFER_BULK:
     175                instance->registers->control &= ~C_BLE;
     176                endpoint_list_add_ep(
     177                    &instance->lists[ep->transfer_type], hcd_ep);
     178                instance->registers->control |= C_BLE;
     179                break;
     180        case USB_TRANSFER_ISOCHRONOUS:
     181        case USB_TRANSFER_INTERRUPT:
     182                instance->registers->control &= (~C_PLE & ~C_IE);
     183                endpoint_list_add_ep(
     184                    &instance->lists[ep->transfer_type], hcd_ep);
     185                instance->registers->control |= C_PLE | C_IE;
     186                break;
     187        default:
     188                break;
     189        }
     190
     191        return EOK;
     192}
     193/*----------------------------------------------------------------------------*/
     194int hc_remove_endpoint(hc_t *instance, usb_address_t address,
     195    usb_endpoint_t endpoint, usb_direction_t direction)
     196{
     197        assert(instance);
     198        fibril_mutex_lock(&instance->guard);
     199        endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
     200            address, endpoint, direction, NULL);
     201        if (ep == NULL) {
     202                usb_log_error("Endpoint unregister failed: No such EP.\n");
     203                fibril_mutex_unlock(&instance->guard);
     204                return ENOENT;
     205        }
     206
     207        hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
     208        if (hcd_ep) {
     209                /* Dequeue hcd_ep */
     210                switch (ep->transfer_type) {
     211                case USB_TRANSFER_CONTROL:
     212                        instance->registers->control &= ~C_CLE;
     213                        endpoint_list_remove_ep(
     214                            &instance->lists[ep->transfer_type], hcd_ep);
     215                        instance->registers->control_current = 0;
     216                        instance->registers->control |= C_CLE;
     217                        break;
     218                case USB_TRANSFER_BULK:
     219                        instance->registers->control &= ~C_BLE;
     220                        endpoint_list_remove_ep(
     221                            &instance->lists[ep->transfer_type], hcd_ep);
     222                        instance->registers->control |= C_BLE;
     223                        break;
     224                case USB_TRANSFER_ISOCHRONOUS:
     225                case USB_TRANSFER_INTERRUPT:
     226                        instance->registers->control &= (~C_PLE & ~C_IE);
     227                        endpoint_list_remove_ep(
     228                            &instance->lists[ep->transfer_type], hcd_ep);
     229                        instance->registers->control |= C_PLE | C_IE;
     230                        break;
     231                default:
     232                        break;
     233                }
     234                hcd_endpoint_clear(ep);
     235        } else {
     236                usb_log_warning("Endpoint without hcd equivalent structure.\n");
     237        }
     238        int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager,
     239            address, endpoint, direction);
     240        fibril_mutex_unlock(&instance->guard);
     241        return ret;
     242}
     243/*----------------------------------------------------------------------------*/
     244endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
     245    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw)
     246{
     247        assert(instance);
     248        fibril_mutex_lock(&instance->guard);
     249        endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
     250            address, endpoint, direction, bw);
     251        fibril_mutex_unlock(&instance->guard);
     252        return ep;
     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:
    143271                instance->registers->command_status |= CS_CLF;
    144                 usb_log_debug2("Set control transfer filled: %x.\n",
    145                         instance->registers->command_status);
    146                 instance->registers->control |= C_CLE;
    147272                break;
    148273        case USB_TRANSFER_BULK:
    149274                instance->registers->command_status |= CS_BLF;
    150                 usb_log_debug2("Set bulk transfer filled: %x.\n",
    151                         instance->registers->command_status);
    152275                break;
    153276        default:
    154277                break;
    155278        }
     279
     280        fibril_mutex_unlock(&instance->guard);
    156281        return EOK;
    157282}
     
    165290                rh_interrupt(&instance->rh);
    166291
    167         usb_log_info("OHCI interrupt: %x.\n", status);
    168 
    169 
    170         LIST_INITIALIZE(done);
    171         transfer_list_remove_finished(&instance->transfers_interrupt, &done);
    172         transfer_list_remove_finished(&instance->transfers_isochronous, &done);
    173         transfer_list_remove_finished(&instance->transfers_control, &done);
    174         transfer_list_remove_finished(&instance->transfers_bulk, &done);
    175 
    176         while (!list_empty(&done)) {
    177                 link_t *item = done.next;
    178                 list_remove(item);
    179                 usb_transfer_batch_t *batch =
    180                     list_get_instance(item, usb_transfer_batch_t, link);
    181                 usb_transfer_batch_finish(batch);
     292        usb_log_debug("OHCI interrupt: %x.\n", status);
     293
     294        if (status & IS_WDH) {
     295                fibril_mutex_lock(&instance->guard);
     296                usb_log_debug2("HCCA: %p-%p(%p).\n", instance->hcca,
     297                    instance->registers->hcca, addr_to_phys(instance->hcca));
     298                usb_log_debug2("Periodic current: %p.\n",
     299                    instance->registers->periodic_current);
     300
     301                link_t *current = instance->pending_batches.next;
     302                while (current != &instance->pending_batches) {
     303                        link_t *next = current->next;
     304                        usb_transfer_batch_t *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;
     312                }
     313                fibril_mutex_unlock(&instance->guard);
    182314        }
    183315}
     
    191323                instance->registers->interrupt_status = status;
    192324                hc_interrupt(instance, status);
    193                 async_usleep(1000);
     325                async_usleep(50000);
    194326        }
    195327        return EOK;
     
    267399            instance->registers->control);
    268400
     401        /* Use HCCA */
     402        instance->registers->hcca = addr_to_phys(instance->hcca);
     403
     404        /* Use queues */
     405        instance->registers->bulk_head =
     406            instance->lists[USB_TRANSFER_BULK].list_head_pa;
     407        usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
     408            instance->lists[USB_TRANSFER_BULK].list_head,
     409            instance->lists[USB_TRANSFER_BULK].list_head_pa);
     410
     411        instance->registers->control_head =
     412            instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
     413        usb_log_debug2("Control HEAD set to: %p(%p).\n",
     414            instance->lists[USB_TRANSFER_CONTROL].list_head,
     415            instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
     416
    269417        /* Enable queues */
    270418        instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
     
    296444        assert(instance);
    297445
    298 #define SETUP_TRANSFER_LIST(type, name) \
     446#define SETUP_ENDPOINT_LIST(type) \
    299447do { \
    300         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); \
    301450        if (ret != EOK) { \
    302                 usb_log_error("Failed(%d) to setup %s transfer list.\n", \
     451                usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
    303452                    ret, name); \
    304                 transfer_list_fini(&instance->transfers_isochronous); \
    305                 transfer_list_fini(&instance->transfers_interrupt); \
    306                 transfer_list_fini(&instance->transfers_control); \
    307                 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]); \
    308457        } \
    309458} while (0)
    310459
    311         SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS");
    312         SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT");
    313         SETUP_TRANSFER_LIST(transfers_control, "CONTROL");
    314         SETUP_TRANSFER_LIST(transfers_bulk, "BULK");
    315 
    316         transfer_list_set_next(&instance->transfers_interrupt,
    317             &instance->transfers_isochronous);
    318 
    319         /* Assign pointers to be used during scheduling */
    320         instance->transfers[USB_TRANSFER_INTERRUPT] =
    321           &instance->transfers_interrupt;
    322         instance->transfers[USB_TRANSFER_ISOCHRONOUS] =
    323           &instance->transfers_interrupt;
    324         instance->transfers[USB_TRANSFER_CONTROL] =
    325           &instance->transfers_control;
    326         instance->transfers[USB_TRANSFER_BULK] =
    327           &instance->transfers_bulk;
    328 
    329         return EOK;
    330 #undef CHECK_RET_CLEAR_RETURN
     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]);
     467
     468        return EOK;
    331469}
    332470/*----------------------------------------------------------------------------*/
     
    342480                return ENOMEM;
    343481        bzero(instance->hcca, sizeof(hcca_t));
    344         instance->registers->hcca = addr_to_phys(instance->hcca);
    345         usb_log_debug2("OHCI HCCA initialized at %p(%p).\n",
    346             instance->hcca, instance->registers->hcca);
    347 
    348         /* Use queues */
    349         instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
    350         usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
    351             instance->transfers_bulk.list_head,
    352             instance->transfers_bulk.list_head_pa);
    353 
    354         instance->registers->control_head =
    355             instance->transfers_control.list_head_pa;
    356         usb_log_debug2("Control HEAD set to: %p(%p).\n",
    357             instance->transfers_control.list_head,
    358             instance->transfers_control.list_head_pa);
     482        usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
    359483
    360484        unsigned i = 0;
    361485        for (; i < 32; ++i) {
    362486                instance->hcca->int_ep[i] =
    363                     instance->transfers_interrupt.list_head_pa;
     487                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
    364488        }
    365489        usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
    366             instance->transfers_interrupt.list_head,
    367             instance->transfers_interrupt.list_head_pa);
     490            instance->lists[USB_TRANSFER_INTERRUPT].list_head,
     491            instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
    368492
    369493        return EOK;
  • uspace/drv/ohci/hc.h

    r3f2af64 rd8b275d  
    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;
    7065        fid_t interrupt_emulator;
     66        fibril_mutex_t guard;
    7167} hc_t;
    7268
     
    7672     uintptr_t regs, size_t reg_size, bool interrupts);
    7773
    78 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
    79 
    80 void hc_interrupt(hc_t *instance, uint32_t status);
    81 
    8274/** Safely dispose host controller internal structures
    8375 *
     
    8577 */
    8678static 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);
    8793
    8894/** Get and cast pointer to the driver data
  • uspace/drv/ohci/hcd_endpoint.h

    r3f2af64 rd8b275d  
    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.c

    r3f2af64 rd8b275d  
    5353                << ED_STATUS_MPS_SHIFT);
    5454
     55
    5556        if (ep->speed == USB_SPEED_LOW)
    5657                instance->status |= ED_STATUS_S_FLAG;
    5758        if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS)
    5859                instance->status |= ED_STATUS_F_FLAG;
     60
     61        if (ep->toggle)
     62                instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
    5963}
    6064/**
  • uspace/drv/ohci/hw_struct/endpoint_descriptor.h

    r3f2af64 rd8b275d  
    5353#define ED_STATUS_D_MASK (0x3)     /* direction */
    5454#define ED_STATUS_D_SHIFT (11)
    55 #define ED_STATUS_D_IN (0x1)
    56 #define ED_STATUS_D_OUT (0x2)
     55#define ED_STATUS_D_OUT (0x1)
     56#define ED_STATUS_D_IN (0x2)
    5757#define ED_STATUS_D_TRANSFER (0x3)
    5858
     
    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         instance->td_head = addr_to_phys(head) & ED_TDHEAD_PTR_MASK;
    87         instance->td_tail = addr_to_phys(tail) & ED_TDTAIL_PTR_MASK;
     86        uintptr_t pa = addr_to_phys(td);
     87        instance->td_head =
     88            ((pa & ED_TDHEAD_PTR_MASK)
     89            | (instance->td_head & ~ED_TDHEAD_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;
    8898}
    8999
     
    96106        instance->next = pa;
    97107}
    98 
    99108#endif
    100109/**
  • uspace/drv/ohci/hw_struct/hcca.h

    r3f2af64 rd8b275d  
    4343        uint32_t done_head;
    4444        uint32_t reserved[29];
    45 } __attribute__((packed)) hcca_t;
     45} __attribute__((packed, aligned)) hcca_t;
    4646
    4747#endif
  • uspace/drv/ohci/hw_struct/transfer_descriptor.c

    r3f2af64 rd8b275d  
    5353        }
    5454        if (buffer != NULL) {
     55                assert(size != 0);
    5556                instance->cbp = addr_to_phys(buffer);
    5657                instance->be = addr_to_phys(buffer + size - 1);
  • uspace/drv/ohci/hw_struct/transfer_descriptor.h

    r3f2af64 rd8b275d  
    5050#define TD_STATUS_DP_SHIFT (19)
    5151#define TD_STATUS_DP_SETUP (0x0)
    52 #define TD_STATUS_DP_IN (0x1)
    53 #define TD_STATUS_DP_OUT (0x2)
     52#define TD_STATUS_DP_OUT (0x1)
     53#define TD_STATUS_DP_IN (0x2)
    5454#define TD_STATUS_DI_MASK (0x7) /* delay interrupt, wait DI frames before int */
    5555#define TD_STATUS_DI_SHIFT (21)
     
    8686        int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
    8787        /* something went wrong, error code is set */
    88         if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2 && cc != CC_NOERROR) {
     88        if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2) {
    8989                return true;
    9090        }
  • uspace/drv/ohci/iface.c

    r3f2af64 rd8b275d  
    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) {
     
    6363        }
    6464
     65        usb_log_debug("%s %d:%d %zu(%zu).\n",
     66            name, target.address, target.endpoint, size, ep->max_packet_size);
     67
    6568        const size_t bw = bandwidth_count_usb11(
    6669            ep->speed, ep->transfer_type, size, ep->max_packet_size);
     
    6871                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
    6972                    "but only %zu is reserved.\n",
    70                     name, target.address, target.endpoint, bw, res_bw);
     73                    target.address, target.endpoint, name, bw, res_bw);
    7174                return ENOSPC;
    7275        }
    73         usb_log_debug("%s %d:%d %zu(%zu).\n",
    74             name, target.address, target.endpoint, size, ep->max_packet_size);
    7576
    7677        *batch = batch_get(
     
    157158        hc_t *hc = fun_to_hc(fun);
    158159        assert(hc);
    159         if (address == hc->rh.address)
    160                 return EOK;
     160
    161161        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
    162162        if (speed >= USB_SPEED_MAX) {
    163163                speed = ep_speed;
    164164        }
    165         const size_t size =
    166             (transfer_type == USB_TRANSFER_INTERRUPT
    167             || transfer_type == USB_TRANSFER_ISOCHRONOUS) ?
    168             max_packet_size : 0;
    169         int ret;
    170 
    171         endpoint_t *ep = malloc(sizeof(endpoint_t));
    172         if (ep == NULL)
    173                 return ENOMEM;
    174         ret = endpoint_init(ep, address, endpoint, direction,
    175             transfer_type, speed, max_packet_size);
    176         if (ret != EOK) {
    177                 free(ep);
    178                 return ret;
    179         }
     165        const size_t size = max_packet_size;
    180166
    181167        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
     
    183169            usb_str_speed(speed), direction, size, max_packet_size, interval);
    184170
    185         ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
    186         if (ret != EOK) {
    187                 endpoint_destroy(ep);
    188         }
    189         return ret;
     171        return hc_add_endpoint(hc, address, endpoint, speed, transfer_type,
     172            direction, max_packet_size, size, interval);
    190173}
    191174/*----------------------------------------------------------------------------*/
     
    198181        usb_log_debug("Unregister endpoint %d:%d %d.\n",
    199182            address, endpoint, direction);
    200         return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
    201             endpoint, direction);
     183        return hc_remove_endpoint(hc, address, endpoint, direction);
    202184}
    203185/*----------------------------------------------------------------------------*/
     
    231213        ret = hc_schedule(hc, batch);
    232214        if (ret != EOK) {
    233                 batch_dispose(batch);
     215                usb_transfer_batch_dispose(batch);
    234216        }
    235217        return ret;
     
    265247        ret = hc_schedule(hc, batch);
    266248        if (ret != EOK) {
    267                 batch_dispose(batch);
     249                usb_transfer_batch_dispose(batch);
    268250        }
    269251        return ret;
     
    299281        ret = hc_schedule(hc, batch);
    300282        if (ret != EOK) {
    301                 batch_dispose(batch);
     283                usb_transfer_batch_dispose(batch);
    302284        }
    303285        return ret;
     
    333315        ret = hc_schedule(hc, batch);
    334316        if (ret != EOK) {
    335                 batch_dispose(batch);
     317                usb_transfer_batch_dispose(batch);
    336318        }
    337319        return ret;
     
    349331 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    350332 *      and deallocated by the caller).
    351  * @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.
    352334 * @param[in] data_buffer Data buffer (in USB endianess, allocated and
    353335 *      deallocated by the caller).
    354  * @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.
    355337 * @param[in] callback Callback to be issued once the transfer is complete.
    356338 * @param[in] arg Pass-through argument to the callback.
     
    373355        ret = hc_schedule(hc, batch);
    374356        if (ret != EOK) {
    375                 batch_dispose(batch);
     357                usb_transfer_batch_dispose(batch);
    376358        }
    377359        return ret;
     
    389371 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    390372 *      and deallocated by the caller).
    391  * @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.
    392374 * @param[in] data_buffer Buffer where to store the data (in USB endianess,
    393375 *      allocated and deallocated by the caller).
    394  * @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.
    395377 * @param[in] callback Callback to be issued once the transfer is complete.
    396378 * @param[in] arg Pass-through argument to the callback.
     
    412394        ret = hc_schedule(hc, batch);
    413395        if (ret != EOK) {
    414                 batch_dispose(batch);
     396                usb_transfer_batch_dispose(batch);
    415397        }
    416398        return ret;
  • uspace/drv/ohci/ohci.ma

    r3f2af64 rd8b275d  
    1110 pci/ven=106b&dev=003f
     210 pci/ven=10de&dev=0aa5
     310 pci/ven=10de&dev=0aa5
  • uspace/drv/ohci/ohci_regs.h

    r3f2af64 rd8b275d  
    100100#define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */
    101101
    102         /** Currently executed period endpoint */
    103         const volatile uint32_t period_current;
     102        /** Currently executed periodic endpoint */
     103        const volatile uint32_t periodic_current;
    104104
    105105        /** The first control endpoint */
  • uspace/drv/ohci/root_hub.c

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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/ohci/utils/malloc32.h

    r3f2af64 rd8b275d  
    4141#include <as.h>
    4242
    43 #define UHCI_STRCUTURES_ALIGNMENT 16
    4443#define UHCI_REQUIRED_PAGE_SIZE 4096
    4544
     
    6564 */
    6665static inline void * malloc32(size_t size)
    67         { return memalign(UHCI_STRCUTURES_ALIGNMENT, size); }
     66        { return memalign(size, size); }
    6867/*----------------------------------------------------------------------------*/
    6968/** Physical mallocator simulator
  • uspace/drv/uhci-hcd/batch.c

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    6363        }
    6464
     65        usb_log_debug("%s %d:%d %zu(%zu).\n",
     66            name, target.address, target.endpoint, size, ep->max_packet_size);
     67
    6568        const size_t bw = bandwidth_count_usb11(
    6669            ep->speed, ep->transfer_type, size, ep->max_packet_size);
     
    6871                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
    6972                    "but only %zu is reserved.\n",
    70                     name, target.address, target.endpoint, bw, res_bw);
     73                    target.address, target.endpoint, name, bw, res_bw);
    7174                return ENOSPC;
    7275        }
    73         usb_log_debug("%s %d:%d %zu(%zu).\n",
    74             name, target.address, target.endpoint, size, ep->max_packet_size);
    7576
    7677        *batch = batch_get(
     
    146147        hc_t *hc = fun_to_hc(fun);
    147148        assert(hc);
     149        const size_t size = max_packet_size;
    148150        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
    149151        if (speed >= USB_SPEED_MAX) {
    150152                speed = ep_speed;
    151153        }
    152         const size_t size =
    153             (transfer_type == USB_TRANSFER_INTERRUPT
    154             || transfer_type == USB_TRANSFER_ISOCHRONOUS) ?
    155             max_packet_size : 0;
    156         int ret;
    157 
    158         endpoint_t *ep = malloc(sizeof(endpoint_t));
    159         if (ep == NULL)
    160                 return ENOMEM;
    161         ret = endpoint_init(ep, address, endpoint, direction,
    162             transfer_type, speed, max_packet_size);
    163         if (ret != EOK) {
    164                 free(ep);
    165                 return ret;
    166         }
    167 
    168154        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    169155            address, endpoint, usb_str_transfer_type(transfer_type),
    170156            usb_str_speed(speed), direction, size, max_packet_size, interval);
    171157
    172         ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
    173         if (ret != EOK) {
    174                 endpoint_destroy(ep);
    175         }
    176         return ret;
     158        return usb_endpoint_manager_add_ep(&hc->ep_manager, address, endpoint,
     159            direction, transfer_type, speed, max_packet_size, size);
    177160}
    178161/*----------------------------------------------------------------------------*/
     
    212195        ret = hc_schedule(hc, batch);
    213196        if (ret != EOK) {
    214                 batch_dispose(batch);
     197                usb_transfer_batch_dispose(batch);
    215198        }
    216199        return ret;
     
    240223        ret = hc_schedule(hc, batch);
    241224        if (ret != EOK) {
    242                 batch_dispose(batch);
     225                usb_transfer_batch_dispose(batch);
    243226        }
    244227        return ret;
     
    268251        ret = hc_schedule(hc, batch);
    269252        if (ret != EOK) {
    270                 batch_dispose(batch);
     253                usb_transfer_batch_dispose(batch);
    271254        }
    272255        return ret;
     
    296279        ret = hc_schedule(hc, batch);
    297280        if (ret != EOK) {
    298                 batch_dispose(batch);
     281                usb_transfer_batch_dispose(batch);
    299282        }
    300283        return ret;
     
    329312        ret = hc_schedule(hc, batch);
    330313        if (ret != EOK) {
    331                 batch_dispose(batch);
     314                usb_transfer_batch_dispose(batch);
    332315        }
    333316        return ret;
     
    361344        ret = hc_schedule(hc, batch);
    362345        if (ret != EOK) {
    363                 batch_dispose(batch);
     346                usb_transfer_batch_dispose(batch);
    364347        }
    365348        return ret;
  • uspace/drv/uhci-hcd/main.c

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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

    r3f2af64 rd8b275d  
    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/**
  • uspace/drv/usbhid/Makefile

    r3f2af64 rd8b275d  
    4040        main.c \
    4141        usbhid.c \
     42        subdrivers.c \
    4243        kbd/conv.c \
    4344        kbd/kbddev.c \
    4445        kbd/kbdrepeat.c \
    4546        generic/hiddev.c \
     47        mouse/mousedev.c \
    4648        $(STOLEN_LAYOUT_SOURCES)
    4749
  • uspace/drv/usbhid/generic/hiddev.c

    r3f2af64 rd8b275d  
    3939
    4040#include "hiddev.h"
     41#include "usbhid.h"
    4142
    4243/*----------------------------------------------------------------------------*/
     
    5455/*----------------------------------------------------------------------------*/
    5556
    56 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
    57      size_t buffer_size, void *arg)
     57bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev,
     58    uint8_t *buffer, size_t buffer_size)
    5859{
    59         usb_log_debug("usb_hid_polling_callback()\n");
     60        usb_log_debug("usb_hid_polling_callback(%p, %p, %zu)\n",
     61            hid_dev, buffer, buffer_size);
    6062        usb_debug_str_buffer(buffer, buffer_size, 0);
    6163        return true;
  • uspace/drv/usbhid/generic/hiddev.h

    r3f2af64 rd8b275d  
    3434 */
    3535
    36 #ifndef USB_HIDD_H_
    37 #define USB_HIDD_H_
     36#ifndef USB_HID_HIDDDEV_H_
     37#define USB_HID_HIDDDEV_H_
    3838
    3939#include <usb/devdrv.h>
     40
     41struct usb_hid_dev;
    4042
    4143usb_endpoint_description_t usb_hid_generic_poll_endpoint_description;
     
    4446const char *HID_GENERIC_CLASS_NAME;
    4547
    46 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
    47      size_t buffer_size, void *arg);
     48bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev,
     49    uint8_t *buffer, size_t buffer_size);
    4850
    49 #endif // USB_HIDD_H_
     51#endif // USB_HID_HIDDDEV_H_
    5052
    5153/**
  • uspace/drv/usbhid/kbd/conv.h

    r3f2af64 rd8b275d  
    3434 */
    3535
    36 #ifndef USB_KBD_CONV_H_
    37 #define USB_KBD_CONV_H_
     36#ifndef USB_HID_CONV_H_
     37#define USB_HID_CONV_H_
    3838
    3939unsigned int usbhid_parse_scancode(int scancode);
    4040
    41 #endif /* USB_KBD_CONV_H_ */
     41#endif /* USB_HID_CONV_H_ */
    4242
    4343/**
  • uspace/drv/usbhid/kbd/kbddev.c

    r3f2af64 rd8b275d  
    238238 * @param icall Call data.
    239239 */
    240 void default_connection_handler(ddf_fun_t *fun,
     240static void default_connection_handler(ddf_fun_t *fun,
    241241    ipc_callid_t icallid, ipc_call_t *icall)
    242242{
     
    856856/*----------------------------------------------------------------------------*/
    857857
    858 bool usb_kbd_polling_callback(usb_device_t *dev, uint8_t *buffer,
    859      size_t buffer_size, void *arg)
    860 {
    861         if (dev == NULL || buffer == NULL || arg == NULL) {
     858bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, uint8_t *buffer,
     859     size_t buffer_size)
     860{
     861        if (hid_dev == NULL || buffer == NULL) {
    862862                // do not continue polling (???)
    863863                return false;
    864864        }
    865        
    866         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    867865       
    868866        // TODO: add return value from this function
     
    916914/*----------------------------------------------------------------------------*/
    917915
    918 void usb_kbd_deinit(struct usb_hid_dev_t *hid_dev)
     916void usb_kbd_deinit(usb_hid_dev_t *hid_dev)
    919917{
    920918        if (hid_dev == NULL) {
  • uspace/drv/usbhid/kbd/kbddev.h

    r3f2af64 rd8b275d  
    3434 */
    3535
    36 #ifndef USB_KBDDEV_H_
    37 #define USB_KBDDEV_H_
     36#ifndef USB_HID_KBDDEV_H_
     37#define USB_HID_KBDDEV_H_
    3838
    3939#include <stdint.h>
     
    4949#include "kbdrepeat.h"
    5050
    51 struct usb_hid_dev_t;
     51struct usb_hid_dev;
    5252
    5353/*----------------------------------------------------------------------------*/
     
    6565 */
    6666typedef struct usb_kbd_t {
    67         /** Structure holding generic USB device information. */
    68         //usbhid_dev_t *hid_dev;
    69         //usb_device_t *usb_dev;
    70        
    7167        /** Currently pressed keys (not translated to key codes). */
    7268        uint8_t *keys;
     
    9187        fibril_mutex_t *repeat_mtx;
    9288       
    93         /** Report descriptor. */
    94         //uint8_t *report_desc;
    95 
    96         /** Report descriptor size. */
    97         //size_t report_desc_size;
    98        
    9989        uint8_t *output_buffer;
    10090       
     
    10696       
    10797        int32_t *led_data;
    108 
    109         /** HID Report parser. */
    110         //usb_hid_report_parser_t *parser;
    11198       
    11299        /** State of the structure (for checking before use).
     
    121108/*----------------------------------------------------------------------------*/
    122109
    123 //enum {
    124 //      USB_KBD_POLL_EP_NO = 0,
    125 //      USB_HID_POLL_EP_NO = 1,
    126 //      USB_KBD_POLL_EP_COUNT = 2
    127 //};
    128 
    129 //usb_endpoint_description_t *usb_kbd_endpoints[USB_KBD_POLL_EP_COUNT + 1];
    130 
    131 //ddf_dev_ops_t keyboard_ops;
    132 
    133110usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description;
    134111
     
    138115/*----------------------------------------------------------------------------*/
    139116
    140 //usb_kbd_t *usb_kbd_new(void);
     117int usb_kbd_init(struct usb_hid_dev *hid_dev);
    141118
    142 int usb_kbd_init(struct usb_hid_dev_t *hid_dev);
    143 
    144 bool usb_kbd_polling_callback(usb_device_t *dev, uint8_t *buffer,
    145      size_t buffer_size, void *arg);
    146 
    147 //void usb_kbd_polling_ended_callback(usb_device_t *dev, bool reason,
    148 //     void *arg);
     119bool usb_kbd_polling_callback(struct usb_hid_dev *hid_dev, uint8_t *buffer,
     120    size_t buffer_size);
    149121
    150122int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev);
     
    154126void usb_kbd_free(usb_kbd_t **kbd_dev);
    155127
    156 void usb_kbd_push_ev(struct usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev,
     128void usb_kbd_push_ev(struct usb_hid_dev *hid_dev, usb_kbd_t *kbd_dev,
    157129    int type, unsigned int key);
    158130
     131void usb_kbd_deinit(struct usb_hid_dev *hid_dev);
    159132
    160 void usb_kbd_deinit(struct usb_hid_dev_t *hid_dev);
     133int usb_kbd_set_boot_protocol(struct usb_hid_dev *hid_dev);
    161134
    162 int usb_kbd_set_boot_protocol(struct usb_hid_dev_t *hid_dev);
    163 
    164 #endif /* USB_KBDDEV_H_ */
     135#endif /* USB_HID_KBDDEV_H_ */
    165136
    166137/**
  • uspace/drv/usbhid/kbd/kbdrepeat.h

    r3f2af64 rd8b275d  
    3434 */
    3535
    36 #ifndef USB_KBDREPEAT_H_
    37 #define USB_KBDREPEAT_H_
     36#ifndef USB_HID_KBDREPEAT_H_
     37#define USB_HID_KBDREPEAT_H_
    3838
    3939struct usb_kbd_t;
     
    6262void usb_kbd_repeat_stop(struct usb_kbd_t *kbd, unsigned int key);
    6363
    64 #endif /* USB_KBDREPEAT_H_ */
     64#endif /* USB_HID_KBDREPEAT_H_ */
    6565
    6666/**
  • uspace/drv/usbhid/layout.h

    r3f2af64 rd8b275d  
    3636 */
    3737
    38 #ifndef USB_KBD_LAYOUT_H_
    39 #define USB_KBD_LAYOUT_H_
     38#ifndef USB_HID_LAYOUT_H_
     39#define USB_HID_LAYOUT_H_
    4040
    4141#include <sys/types.h>
  • uspace/drv/usbhid/main.c

    r3f2af64 rd8b275d  
    9898        /* Create the function exposed under /dev/devices. */
    9999        ddf_fun_t *hid_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
    100             usb_hid_get_function_name(hid_dev->device_type));
     100            usb_hid_get_function_name(hid_dev));
    101101        if (hid_fun == NULL) {
    102102                usb_log_error("Could not create DDF function node.\n");
     
    122122        }
    123123       
    124         rc = ddf_fun_add_to_class(hid_fun,
    125             usb_hid_get_class_name(hid_dev->device_type));
     124        rc = ddf_fun_add_to_class(hid_fun, usb_hid_get_class_name(hid_dev));
    126125        if (rc != EOK) {
    127126                usb_log_error(
     
    142141           hid_dev->poll_pipe_index,
    143142           /* Callback when data arrives. */
    144            hid_dev->poll_callback,
     143           usb_hid_polling_callback,
    145144           /* How much data to request. */
    146145           dev->pipes[hid_dev->poll_pipe_index].pipe->max_packet_size,
  • uspace/drv/usbhid/subdrivers.c

    r3f2af64 rd8b275d  
    11/*
    2  * Copyright (c) 2007 Jan Hudecek
    3  * Copyright (c) 2008 Martin Decky
     2 * Copyright (c) 2011 Lubos Slovak
    43 * All rights reserved.
    54 *
     
    2827 */
    2928
    30 /** @addtogroup genericproc
     29/** @addtogroup drvusbhid
    3130 * @{
    3231 */
    33 /** @file tasklet.c
    34  *  @brief Tasklet implementation
     32/** @file
     33 * USB HID subdriver mappings.
    3534 */
    3635
    37 #include <proc/tasklet.h>
    38 #include <synch/spinlock.h>
    39 #include <mm/slab.h>
    40 #include <config.h>
     36#include "subdrivers.h"
     37#include "usb/classes/hidut.h"
    4138
    42 /** Spinlock protecting list of tasklets */
    43 SPINLOCK_INITIALIZE(tasklet_lock);
     39static usb_hid_subdriver_usage_t path_kbd[] = {{USB_HIDUT_PAGE_KEYBOARD, 0}};
    4440
    45 /** Array of tasklet lists for every CPU */
    46 tasklet_descriptor_t **tasklet_list;
     41const usb_hid_subdriver_mapping_t usb_hid_subdrivers[] = {
     42        {
     43                path_kbd,
     44                1,
     45                USB_HID_PATH_COMPARE_END
     46                | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     47                NULL,
     48                NULL,
     49                {
     50                        usb_kbd_init,
     51                        usb_kbd_deinit,
     52                        usb_kbd_polling_callback,
     53                        NULL
     54                },
     55               
     56        },
     57        {NULL, 0, 0, NULL, NULL, {NULL, NULL, NULL, NULL}}
     58};
    4759
    48 void tasklet_init(void)
    49 {
    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");
    60 }
    61 
    62 
    63 /** @}
     60/**
     61 * @}
    6462 */
  • uspace/drv/usbhid/usbhid.c

    r3f2af64 rd8b275d  
    4242#include <usb/classes/hidreq.h>
    4343#include <errno.h>
     44#include <str_error.h>
    4445
    4546#include "usbhid.h"
     
    4748#include "kbd/kbddev.h"
    4849#include "generic/hiddev.h"
    49 
    50 /*----------------------------------------------------------------------------*/
    51 
    52 /** Mouse polling endpoint description for boot protocol class. */
    53 static usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
    54         .transfer_type = USB_TRANSFER_INTERRUPT,
    55         .direction = USB_DIRECTION_IN,
    56         .interface_class = USB_CLASS_HID,
    57         .interface_subclass = USB_HID_SUBCLASS_BOOT,
    58         .interface_protocol = USB_HID_PROTOCOL_MOUSE,
    59         .flags = 0
    60 };
     50#include "mouse/mousedev.h"
     51#include "subdrivers.h"
     52
     53/*----------------------------------------------------------------------------*/
    6154
    6255/* Array of endpoints expected on the device, NULL terminated. */
     
    6861};
    6962
    70 static const char *HID_MOUSE_FUN_NAME = "mouse";
    71 static const char *HID_MOUSE_CLASS_NAME = "mouse";
     63static const int USB_HID_MAX_SUBDRIVERS = 10;
     64
     65/*----------------------------------------------------------------------------*/
     66
     67static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
     68{
     69        assert(hid_dev->subdriver_count == 0);
     70       
     71        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     72            sizeof(usb_hid_subdriver_t));
     73        if (hid_dev->subdrivers == NULL) {
     74                return ENOMEM;
     75        }
     76       
     77        // set the init callback
     78        hid_dev->subdrivers[0].init = usb_kbd_init;
     79       
     80        // set the polling callback
     81        hid_dev->subdrivers[0].poll = usb_kbd_polling_callback;
     82       
     83        // set the polling ended callback
     84        hid_dev->subdrivers[0].poll_end = NULL;
     85       
     86        // set the deinit callback
     87        hid_dev->subdrivers[0].deinit = usb_kbd_deinit;
     88       
     89        // set subdriver count
     90        hid_dev->subdriver_count = 1;
     91       
     92        return EOK;
     93}
     94
     95/*----------------------------------------------------------------------------*/
     96
     97static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
     98{
     99        assert(hid_dev->subdriver_count == 0);
     100       
     101        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     102            sizeof(usb_hid_subdriver_t));
     103        if (hid_dev->subdrivers == NULL) {
     104                return ENOMEM;
     105        }
     106       
     107        // set the init callback
     108        hid_dev->subdrivers[0].init = usb_mouse_init;
     109       
     110        // set the polling callback
     111        hid_dev->subdrivers[0].poll = usb_mouse_polling_callback;
     112       
     113        // set the polling ended callback
     114        hid_dev->subdrivers[0].poll_end = NULL;
     115       
     116        // set the deinit callback
     117        hid_dev->subdrivers[0].deinit = usb_mouse_deinit;
     118       
     119        // set subdriver count
     120        hid_dev->subdriver_count = 1;
     121       
     122        return EOK;
     123}
     124
     125/*----------------------------------------------------------------------------*/
     126
     127static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
     128{
     129        assert(hid_dev->subdriver_count == 0);
     130       
     131        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     132            sizeof(usb_hid_subdriver_t));
     133        if (hid_dev->subdrivers == NULL) {
     134                return ENOMEM;
     135        }
     136       
     137        // set the init callback
     138        hid_dev->subdrivers[0].init = NULL;
     139       
     140        // set the polling callback
     141        hid_dev->subdrivers[0].poll = usb_generic_hid_polling_callback;
     142       
     143        // set the polling ended callback
     144        hid_dev->subdrivers[0].poll_end = NULL;
     145       
     146        // set the deinit callback
     147        hid_dev->subdrivers[0].deinit = NULL;
     148       
     149        // set subdriver count
     150        hid_dev->subdriver_count = 1;
     151       
     152        return EOK;
     153}
     154
     155/*----------------------------------------------------------------------------*/
     156
     157static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev,
     158    const usb_hid_subdriver_mapping_t *mapping)
     159{
     160        return false;
     161}
     162
     163/*----------------------------------------------------------------------------*/
     164
     165static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
     166    const usb_hid_subdriver_usage_t *path, int path_size, int compare)
     167{
     168        assert(hid_dev != NULL);
     169        assert(path != NULL);
     170       
     171        usb_hid_report_path_t *usage_path = usb_hid_report_path();
     172        if (usage_path == NULL) {
     173                usb_log_debug("Failed to create usage path.\n");
     174                return false;
     175        }
     176        int i;
     177        for (i = 0; i < path_size; ++i) {
     178                if (usb_hid_report_path_append_item(usage_path,
     179                    path[i].usage_page, path[i].usage) != EOK) {
     180                        usb_log_debug("Failed to append to usage path.\n");
     181                        usb_hid_report_path_free(usage_path);
     182                        return false;
     183                }
     184        }
     185       
     186        assert(hid_dev->parser != NULL);
     187       
     188        usb_log_debug("Compare flags: %d\n", compare);
     189        size_t size = usb_hid_report_input_length(hid_dev->parser, usage_path,
     190            compare);
     191        usb_log_debug("Size of the input report: %d\n", size);
     192       
     193        usb_hid_report_path_free(usage_path);
     194       
     195        return (size > 0);
     196}
     197
     198/*----------------------------------------------------------------------------*/
     199
     200static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
     201    const usb_hid_subdriver_t **subdrivers, int count)
     202{
     203        int i;
     204       
     205        if (count <= 0) {
     206                hid_dev->subdriver_count = 0;
     207                hid_dev->subdrivers = NULL;
     208                return EOK;
     209        }
     210       
     211        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(count *
     212            sizeof(usb_hid_subdriver_t));
     213        if (hid_dev->subdrivers == NULL) {
     214                return ENOMEM;
     215        }
     216       
     217        for (i = 0; i < count; ++i) {
     218                hid_dev->subdrivers[i].init = subdrivers[i]->init;
     219                hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
     220                hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
     221                hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
     222        }
     223       
     224        hid_dev->subdriver_count = count;
     225       
     226        return EOK;
     227}
     228
     229/*----------------------------------------------------------------------------*/
     230
     231static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
     232{
     233        const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
     234       
     235        int i = 0, count = 0;
     236        const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
     237       
     238        while (count < USB_HID_MAX_SUBDRIVERS &&
     239            (mapping->usage_path != NULL
     240            || mapping->vendor_id != NULL
     241            || mapping->product_id != NULL)) {
     242                // check the vendor & product ID
     243                if (mapping->vendor_id != NULL && mapping->product_id == NULL) {
     244                        usb_log_warning("Missing Product ID for Vendor ID %s\n",
     245                            mapping->vendor_id);
     246                        return EINVAL;
     247                }
     248                if (mapping->product_id != NULL && mapping->vendor_id == NULL) {
     249                        usb_log_warning("Missing Vendor ID for Product ID %s\n",
     250                            mapping->product_id);
     251                        return EINVAL;
     252                }
     253               
     254                if (mapping->vendor_id != NULL) {
     255                        assert(mapping->product_id != NULL);
     256                        usb_log_debug("Comparing device against vendor ID %s"
     257                            " and product ID %s.\n", mapping->vendor_id,
     258                            mapping->product_id);
     259                        if (usb_hid_ids_match(hid_dev, mapping)) {
     260                                usb_log_debug("Matched.\n");
     261                                subdrivers[count++] = &mapping->subdriver;
     262                                // skip the checking of usage path
     263                                goto next;
     264                        }
     265                }
     266               
     267                if (mapping->usage_path != NULL) {
     268                        usb_log_debug("Comparing device against usage path.\n");
     269                        if (usb_hid_path_matches(hid_dev,
     270                            mapping->usage_path, mapping->path_size,
     271                            mapping->compare)) {
     272                                subdrivers[count++] = &mapping->subdriver;
     273                        } else {
     274                                usb_log_debug("Not matched.\n");
     275                        }
     276                }
     277        next:
     278                mapping = &usb_hid_subdrivers[++i];
     279        }
     280       
     281        // we have all subdrivers determined, save them into the hid device
     282        return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
     283}
     284
     285/*----------------------------------------------------------------------------*/
     286
     287static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
     288{
     289        int rc = EOK;
     290       
     291        if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
     292                usb_log_debug("Found keyboard endpoint.\n");
     293                // save the pipe index
     294                hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
     295        } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
     296                usb_log_debug("Found mouse endpoint.\n");
     297                // save the pipe index
     298                hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
     299        } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
     300                usb_log_debug("Found generic HID endpoint.\n");
     301                // save the pipe index
     302                hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
     303        } else {
     304                usb_log_error("None of supported endpoints found - probably"
     305                    " not a supported device.\n");
     306                rc = ENOTSUP;
     307        }
     308       
     309        return rc;
     310}
    72311
    73312/*----------------------------------------------------------------------------*/
     
    91330        }
    92331       
     332        hid_dev->poll_pipe_index = -1;
     333       
    93334        return hid_dev;
    94335}
     
    96337/*----------------------------------------------------------------------------*/
    97338
    98 static bool usb_dummy_polling_callback(usb_device_t *dev, uint8_t *buffer,
    99      size_t buffer_size, void *arg)
    100 {
    101         usb_log_debug("Dummy polling callback.\n");
    102         return false;
    103 }
    104 
    105 /*----------------------------------------------------------------------------*/
    106 
    107 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    108 {
    109         if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
    110                 usb_log_debug("Found keyboard endpoint.\n");
    111                
    112                 // save the pipe index and device type
    113                 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
    114                 hid_dev->device_type = USB_HID_PROTOCOL_KEYBOARD;
    115                
    116                 // set the polling callback
    117                 hid_dev->poll_callback = usb_kbd_polling_callback;
    118 
    119         } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
    120                 usb_log_debug("Found mouse endpoint.\n");
    121                
    122                 // save the pipe index and device type
    123                 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
    124                 hid_dev->device_type = USB_HID_PROTOCOL_MOUSE;
    125                
    126                 // set the polling callback
    127                 hid_dev->poll_callback = usb_dummy_polling_callback;
    128                
    129         } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
    130                 usb_log_debug("Found generic HID endpoint.\n");
    131                
    132                 // save the pipe index and device type
    133                 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
    134                 hid_dev->device_type = USB_HID_PROTOCOL_NONE;
    135                
    136                 // set the polling callback
    137                 hid_dev->poll_callback = usb_hid_polling_callback;
    138                
    139         } else {
    140                 usb_log_warning("None of supported endpoints found - probably"
    141                     " not a supported device.\n");
    142                 return ENOTSUP;
    143         }
    144        
    145         return EOK;
    146 }
    147 
    148 /*----------------------------------------------------------------------------*/
    149 
    150 static int usb_hid_init_parser(usb_hid_dev_t *hid_dev)
    151 {
    152         /* Initialize the report parser. */
    153         int rc = usb_hid_parser_init(hid_dev->parser);
    154         if (rc != EOK) {
    155                 usb_log_error("Failed to initialize report parser.\n");
    156                 return rc;
    157         }
    158        
    159         /* Get the report descriptor and parse it. */
    160         rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
    161             hid_dev->parser);
    162        
    163         if (rc != EOK) {
    164                 usb_log_warning("Could not process report descriptor.\n");
    165                
    166                 if (hid_dev->device_type == USB_HID_PROTOCOL_KEYBOARD) {
    167                         usb_log_warning("Falling back to boot protocol.\n");
    168                        
    169                         rc = usb_kbd_set_boot_protocol(hid_dev);
    170                        
    171                 } else if (hid_dev->device_type == USB_HID_PROTOCOL_MOUSE) {
    172                         usb_log_warning("No boot protocol for mouse yet.\n");
    173                         rc = ENOTSUP;
    174                 }
    175         }
    176        
    177         return rc;
    178 }
    179 
    180 /*----------------------------------------------------------------------------*/
    181 
    182339int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    183340{
    184         int rc;
     341        int rc, i;
    185342       
    186343        usb_log_debug("Initializing HID structure...\n");
     
    203360        rc = usb_hid_check_pipes(hid_dev, dev);
    204361        if (rc != EOK) {
     362                usb_hid_free(&hid_dev);
    205363                return rc;
    206364        }
    207365       
    208         rc = usb_hid_init_parser(hid_dev);
     366        /* Initialize the report parser. */
     367        rc = usb_hid_parser_init(hid_dev->parser);
    209368        if (rc != EOK) {
    210                 usb_log_error("Failed to initialize HID parser.\n");
     369                usb_log_error("Failed to initialize report parser.\n");
     370                usb_hid_free(&hid_dev);
    211371                return rc;
    212372        }
    213373       
    214         switch (hid_dev->device_type) {
    215         case USB_HID_PROTOCOL_KEYBOARD:
    216                 // initialize the keyboard structure
    217                 rc = usb_kbd_init(hid_dev);
    218                 if (rc != EOK) {
    219                         usb_log_warning("Failed to initialize KBD structure."
    220                             "\n");
    221                 }
    222                 break;
    223         case USB_HID_PROTOCOL_MOUSE:
    224                 break;
    225         default:
    226 //              usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    227 //                  hid_dev->usb_dev->interface_no, 0);
    228                 break;
     374        /* Get the report descriptor and parse it. */
     375        rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
     376            hid_dev->parser);
     377       
     378        bool fallback = false;
     379       
     380        if (rc == EOK) {
     381                // try to find subdrivers that may want to handle this device
     382                rc = usb_hid_find_subdrivers(hid_dev);
     383                if (rc != EOK || hid_dev->subdriver_count == 0) {
     384                        // try to fall back to the boot protocol if available
     385                        usb_log_info("No subdrivers found to handle this"
     386                            " device.\n");
     387                        fallback = true;
     388                }
     389        } else {
     390                usb_log_error("Failed to parse Report descriptor.\n");
     391                // try to fall back to the boot protocol if available
     392                fallback = true;
     393        }
     394       
     395        // TODO: remove the mouse hack
     396        if (hid_dev->poll_pipe_index == USB_HID_MOUSE_POLL_EP_NO ||
     397            fallback) {
     398                // fall back to boot protocol
     399                switch (hid_dev->poll_pipe_index) {
     400                case USB_HID_KBD_POLL_EP_NO:
     401                        usb_log_info("Falling back to kbd boot protocol.\n");
     402                        rc = usb_kbd_set_boot_protocol(hid_dev);
     403                        if (rc == EOK) {
     404                                rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
     405                        }
     406                        break;
     407                case USB_HID_MOUSE_POLL_EP_NO:
     408                        usb_log_info("Falling back to mouse boot protocol.\n");
     409                        rc = usb_mouse_set_boot_protocol(hid_dev);
     410                        if (rc == EOK) {
     411                                rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
     412                        }
     413                        break;
     414                default:
     415                        assert(hid_dev->poll_pipe_index
     416                            == USB_HID_GENERIC_POLL_EP_NO);
     417                       
     418                        /* TODO: this has no meaning if the report descriptor
     419                                 is not parsed */
     420                        usb_log_info("Falling back to generic HID driver.\n");
     421                        rc = usb_hid_set_generic_hid_subdriver(hid_dev);
     422                }
     423        }
     424       
     425        if (rc != EOK) {
     426                usb_log_error("No subdriver for handling this device could be"
     427                    " initialized: %s.\n", str_error(rc));
     428                usb_hid_free(&hid_dev);
     429        } else {
     430                bool ok = false;
     431               
     432                usb_log_debug("Subdriver count: %d\n",
     433                    hid_dev->subdriver_count);
     434               
     435                for (i = 0; i < hid_dev->subdriver_count; ++i) {
     436                        if (hid_dev->subdrivers[i].init != NULL) {
     437                                usb_log_debug("Initializing subdriver %d.\n",i);
     438                                rc = hid_dev->subdrivers[i].init(hid_dev);
     439                                if (rc != EOK) {
     440                                        usb_log_warning("Failed to initialize"
     441                                            " HID subdriver structure.\n");
     442                                } else {
     443                                        // at least one subdriver initialized
     444                                        ok = true;
     445                                }
     446                        } else {
     447                                ok = true;
     448                        }
     449                }
     450               
     451                rc = (ok) ? EOK : -1;   // what error to report
    229452        }
    230453       
    231454        return rc;
     455}
     456
     457/*----------------------------------------------------------------------------*/
     458
     459bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
     460    size_t buffer_size, void *arg)
     461{
     462        int i;
     463       
     464        if (dev == NULL || arg == NULL || buffer == NULL) {
     465                usb_log_error("Missing arguments to polling callback.\n");
     466                return false;
     467        }
     468       
     469        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
     470       
     471        bool cont = false;
     472       
     473        // continue if at least one of the subdrivers want to continue
     474        for (i = 0; i < hid_dev->subdriver_count; ++i) {
     475                if (hid_dev->subdrivers[i].poll != NULL
     476                    && hid_dev->subdrivers[i].poll(hid_dev, buffer,
     477                    buffer_size)) {
     478                        cont = true;
     479                }
     480        }
     481       
     482        return cont;
    232483}
    233484
     
    237488     void *arg)
    238489{
     490        int i;
     491       
    239492        if (dev == NULL || arg == NULL) {
    240493                return;
     
    243496        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    244497       
     498        for (i = 0; i < hid_dev->subdriver_count; ++i) {
     499                if (hid_dev->subdrivers[i].poll_end != NULL) {
     500                        hid_dev->subdrivers[i].poll_end(hid_dev, reason);
     501                }
     502        }
     503       
    245504        usb_hid_free(&hid_dev);
    246505}
     
    248507/*----------------------------------------------------------------------------*/
    249508
    250 const char *usb_hid_get_function_name(usb_hid_iface_protocol_t device_type)
    251 {
    252         switch (device_type) {
    253         case USB_HID_PROTOCOL_KEYBOARD:
     509const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)
     510{
     511        switch (hid_dev->poll_pipe_index) {
     512        case USB_HID_KBD_POLL_EP_NO:
    254513                return HID_KBD_FUN_NAME;
    255514                break;
    256         case USB_HID_PROTOCOL_MOUSE:
     515        case USB_HID_MOUSE_POLL_EP_NO:
    257516                return HID_MOUSE_FUN_NAME;
    258517                break;
     
    264523/*----------------------------------------------------------------------------*/
    265524
    266 const char *usb_hid_get_class_name(usb_hid_iface_protocol_t device_type)
    267 {
    268         switch (device_type) {
    269         case USB_HID_PROTOCOL_KEYBOARD:
     525const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)
     526{
     527        // this means that only boot protocol keyboards will be connected
     528        // to the console; there is probably no better way to do this
     529       
     530        switch (hid_dev->poll_pipe_index) {
     531        case USB_HID_KBD_POLL_EP_NO:
    270532                return HID_KBD_CLASS_NAME;
    271533                break;
    272         case USB_HID_PROTOCOL_MOUSE:
     534        case USB_HID_MOUSE_POLL_EP_NO:
    273535                return HID_MOUSE_CLASS_NAME;
    274536                break;
     
    282544void usb_hid_free(usb_hid_dev_t **hid_dev)
    283545{
     546        int i;
     547       
    284548        if (hid_dev == NULL || *hid_dev == NULL) {
    285549                return;
    286550        }
    287551       
    288         switch ((*hid_dev)->device_type) {
    289         case USB_HID_PROTOCOL_KEYBOARD:
    290                 usb_kbd_deinit(*hid_dev);
    291                 break;
    292         case USB_HID_PROTOCOL_MOUSE:
    293                 break;
    294         default:
    295                 break;
     552        assert((*hid_dev)->subdrivers != NULL
     553            || (*hid_dev)->subdriver_count == 0);
     554       
     555        for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
     556                if ((*hid_dev)->subdrivers[i].deinit != NULL) {
     557                        (*hid_dev)->subdrivers[i].deinit(*hid_dev);
     558                }
     559        }
     560       
     561        // free the subdrivers info
     562        if ((*hid_dev)->subdrivers != NULL) {
     563                free((*hid_dev)->subdrivers);
    296564        }
    297565
  • uspace/drv/usbhid/usbhid.h

    r3f2af64 rd8b275d  
    3434 */
    3535
    36 #ifndef USB_USBHID_H_
    37 #define USB_USBHID_H_
     36#ifndef USB_HID_USBHID_H_
     37#define USB_HID_USBHID_H_
    3838
    3939#include <stdint.h>
     
    4545#include <usb/classes/hid.h>
    4646
     47struct usb_hid_dev;
     48
     49typedef int (*usb_hid_driver_init_t)(struct usb_hid_dev *);
     50typedef void (*usb_hid_driver_deinit_t)(struct usb_hid_dev *);
     51typedef bool (*usb_hid_driver_poll)(struct usb_hid_dev *, uint8_t *, size_t);
     52typedef int (*usb_hid_driver_poll_ended)(struct usb_hid_dev *, bool reason);
     53
     54// TODO: add function and class name??
     55typedef struct usb_hid_subdriver {     
     56        /** Function to be called when initializing HID device. */
     57        usb_hid_driver_init_t init;
     58        /** Function to be called when destroying the HID device structure. */
     59        usb_hid_driver_deinit_t deinit;
     60        /** Function to be called when data arrives from the device. */
     61        usb_hid_driver_poll poll;
     62        /** Function to be called when polling ends. */
     63        usb_hid_driver_poll_ended poll_end;
     64} usb_hid_subdriver_t;
     65
    4766/*----------------------------------------------------------------------------*/
    4867/**
    4968 * Structure for holding general HID device data.
    5069 */
    51 typedef struct usb_hid_dev_t {
     70typedef struct usb_hid_dev {
    5271        /** Structure holding generic USB device information. */
    5372        usb_device_t *usb_dev;
     
    5978        int poll_pipe_index;
    6079       
    61         /** Function to be called when data arrives from the device. */
    62         usb_polling_callback_t poll_callback;
     80        /** Subdrivers. */
     81        usb_hid_subdriver_t *subdrivers;
     82       
     83        /** Number of subdrivers. */
     84        int subdriver_count;
    6385       
    6486        /** Report descriptor. */
     
    7395        /** Arbitrary data (e.g. a special structure for handling keyboard). */
    7496        void *data;
    75        
    76         /** Type of the device (keyboard, mouse, generic HID device). */
    77         usb_hid_iface_protocol_t device_type;
    7897} usb_hid_dev_t;
    7998
     
    95114int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev);
    96115
     116bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
     117    size_t buffer_size, void *arg);
     118
    97119void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason,
    98120     void *arg);
    99121
    100 const char *usb_hid_get_function_name(usb_hid_iface_protocol_t device_type);
     122const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);
    101123
    102 const char *usb_hid_get_class_name(usb_hid_iface_protocol_t device_type);
     124const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
    103125
    104126void usb_hid_free(usb_hid_dev_t **hid_dev);
    105127
    106 #endif /* USB_USBHID_H_ */
     128#endif /* USB_HID_USBHID_H_ */
    107129
    108130/**
  • uspace/drv/usbhid/usbhid.ma

    r3f2af64 rd8b275d  
    11100 usb&interface&class=HID&subclass=0x01&protocol=0x01
    2 100 usb&interface&class=HID&subclass=0x01&protocol=0x02
     21000 usb&interface&class=HID&subclass=0x01&protocol=0x02
    33100 usb&interface&class=HID
  • uspace/drv/usbhub/usbhub.c

    r3f2af64 rd8b275d  
    247247        for (port = 0; port < hub_info->port_count + 1; port++) {
    248248                usb_hub_port_init(&hub_info->ports[port]);
     249        }
     250        for (port = 0; port < hub_info->port_count; port++) {
     251                opResult = usb_hub_set_port_feature(hub_info->control_pipe,
     252                    port+1, USB_HUB_FEATURE_PORT_POWER);
     253                if (opResult != EOK) {
     254                        usb_log_error("cannot power on port %d;  %d\n",
     255                            port+1, opResult);
     256                }
    249257        }
    250258        usb_log_debug2("freeing data\n");
Note: See TracChangeset for help on using the changeset viewer.