Changeset e1dbcbc in mainline for uspace/drv/ohci


Ignore:
Timestamp:
2011-04-29T13:43:01Z (15 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/fix-logger-deadlock, topic/msim-upgrade, topic/simplify-dev-export
Children:
a81a1d09
Parents:
380e0364 (diff), f19f1b7 (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/ohci
Files:
1 added
18 edited
3 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/ohci/Makefile

    r380e0364 re1dbcbc  
    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

    r380e0364 re1dbcbc  
    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 %zu 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;
     149        instance->transfered_size = instance->buffer_size;
    139150        for (; i < tds; ++i) {
    140                 if (!td_is_finished(&data->tds[i]))
     151                assert(data->tds[i] != NULL);
     152                usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i,
     153                    data->tds[i]->status, data->tds[i]->cbp, data->tds[i]->next,
     154                    data->tds[i]->be);
     155                if (!td_is_finished(data->tds[i])) {
    141156                        return false;
    142                 instance->error = td_error(&data->tds[i]);
    143                 /* FIXME: calculate real transfered size */
    144                 instance->transfered_size = instance->buffer_size;
     157                }
     158                instance->error = td_error(data->tds[i]);
    145159                if (instance->error != EOK) {
    146                         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,
     160                        usb_log_debug("Batch(%p) found error TD(%zu):%x.\n",
     161                            instance, i, data->tds[i]->status);
     162                        /* Make sure TD queue is empty (one TD),
     163                         * ED should be marked as halted */
     164                        data->ed->td_tail =
     165                            (data->ed->td_head & ED_TDTAIL_PTR_MASK);
     166                        ++i;
     167                        break;
    150168                }
    151169        }
     170        data->leave_td = i;
     171        assert(data->leave_td <= data->td_count);
     172        hcd_endpoint_t *hcd_ep = hcd_endpoint_get(instance->ep);
     173        assert(hcd_ep);
     174        hcd_ep->td = data->tds[i];
     175        if (i > 0)
     176                instance->transfered_size -= td_remain_size(data->tds[i - 1]);
     177
     178        /* Clear possible ED HALT */
     179        data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
     180        uint32_t pa = addr_to_phys(hcd_ep->td);
     181        assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK));
     182        assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK));
     183
    152184        return true;
    153185}
    154186/*----------------------------------------------------------------------------*/
     187void batch_commit(usb_transfer_batch_t *instance)
     188{
     189        assert(instance);
     190        ohci_transfer_batch_t *data = instance->private_data;
     191        assert(data);
     192        ed_set_end_td(data->ed, data->tds[data->td_count]);
     193}
     194/*----------------------------------------------------------------------------*/
    155195void batch_control_write(usb_transfer_batch_t *instance)
    156196{
    157197        assert(instance);
    158198        /* 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;
     199        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     200        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    162201        batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
    163202        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
     
    167206{
    168207        assert(instance);
    169         instance->next_step = batch_call_in_and_dispose;
     208        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    170209        batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
    171210        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
     
    175214{
    176215        assert(instance);
    177         assert(instance->direction == USB_DIRECTION_IN);
    178         instance->next_step = batch_call_in_and_dispose;
    179         /* TODO: implement */
     216        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     217        batch_data(instance);
    180218        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    181219}
     
    184222{
    185223        assert(instance);
    186         assert(instance->direction == USB_DIRECTION_OUT);
    187224        /* 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 */
     225        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     226        instance->next_step = usb_transfer_batch_call_out_and_dispose;
     227        batch_data(instance);
    192228        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    193229}
     
    196232{
    197233        assert(instance);
    198         instance->direction = USB_DIRECTION_IN;
    199         instance->next_step = batch_call_in_and_dispose;
    200         /* TODO: implement */
     234        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     235        batch_data(instance);
    201236        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    202237}
     
    205240{
    206241        assert(instance);
    207         instance->direction = USB_DIRECTION_IN;
    208         instance->next_step = batch_call_in_and_dispose;
    209         /* TODO: implement */
    210         usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     242        /* We are data out, we are supposed to provide data */
     243        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     244        instance->next_step = usb_transfer_batch_call_out_and_dispose;
     245        batch_data(instance);
     246        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
    211247}
    212248/*----------------------------------------------------------------------------*/
     
    214250{
    215251        assert(instance);
    216         ohci_batch_t *data = instance->private_data;
     252        ohci_transfer_batch_t *data = instance->private_data;
    217253        assert(data);
    218254        return data->ed;
     
    223259{
    224260        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,
     261        ohci_transfer_batch_t *data = instance->private_data;
     262        assert(data);
     263        usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
    230264            data->ed->status, data->ed->td_tail, data->ed->td_head,
    231265            data->ed->next);
    232266        int toggle = 0;
    233267        /* setup stage */
    234         td_init(&data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
     268        td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
    235269                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);
     270        td_set_next(data->tds[0], data->tds[1]);
     271        usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0]->status,
     272            data->tds[0]->cbp, data->tds[0]->next, data->tds[0]->be);
    239273
    240274        /* data stage */
    241275        size_t td_current = 1;
    242276        size_t remain_size = instance->buffer_size;
    243         char *transfer_buffer = instance->transport_buffer;
     277        char *buffer = instance->data_buffer;
    244278        while (remain_size > 0) {
    245279                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     
    247281                toggle = 1 - toggle;
    248282
    249                 td_init(&data->tds[td_current], data_dir, transfer_buffer,
     283                td_init(data->tds[td_current], data_dir, buffer,
    250284                    transfer_size, toggle);
    251                 td_set_next(&data->tds[td_current], &data->tds[td_current + 1]);
     285                td_set_next(data->tds[td_current], data->tds[td_current + 1]);
    252286                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;
     287                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     288                    data->tds[td_current]->next, data->tds[td_current]->be);
     289
     290                buffer += transfer_size;
    257291                remain_size -= transfer_size;
    258                 assert(td_current < data->td_count - 2);
     292                assert(td_current < data->td_count - 1);
    259293                ++td_current;
    260294        }
    261295
    262296        /* status stage */
    263         assert(td_current == data->td_count - 2);
    264         td_init(&data->tds[td_current], status_dir, NULL, 0, 1);
     297        assert(td_current == data->td_count - 1);
     298        td_init(data->tds[td_current], status_dir, NULL, 0, 1);
     299        td_set_next(data->tds[td_current], data->tds[td_current + 1]);
    265300        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);
     301            data->tds[td_current]->status, data->tds[td_current]->cbp,
     302            data->tds[td_current]->next, data->tds[td_current]->be);
     303}
     304/*----------------------------------------------------------------------------*/
     305void batch_data(usb_transfer_batch_t *instance)
     306{
     307        assert(instance);
     308        ohci_transfer_batch_t *data = instance->private_data;
     309        assert(data);
     310        usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
     311            data->ed->status, data->ed->td_tail, data->ed->td_head,
     312            data->ed->next);
     313
     314        size_t td_current = 0;
     315        size_t remain_size = instance->buffer_size;
     316        char *buffer = instance->data_buffer;
     317        while (remain_size > 0) {
     318                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     319                    OHCI_TD_MAX_TRANSFER : remain_size;
     320
     321                td_init(data->tds[td_current], instance->ep->direction,
     322                    buffer, transfer_size, -1);
     323                td_set_next(data->tds[td_current], data->tds[td_current + 1]);
     324                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
     325                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     326                    data->tds[td_current]->next, data->tds[td_current]->be);
     327
     328                buffer += transfer_size;
     329                remain_size -= transfer_size;
     330                assert(td_current < data->td_count);
     331                ++td_current;
     332        }
    290333}
    291334/**
  • uspace/drv/ohci/batch.h

    r380e0364 re1dbcbc  
    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

    r380e0364 re1dbcbc  
    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);
     
    5855        }
    5956        instance->list_head_pa = addr_to_phys(instance->list_head);
    60         usb_log_debug2("Transfer list %s setup with ED: %p(%p).\n",
     57        usb_log_debug2("Transfer list %s setup with ED: %p(0x%0" PRIx32 ")).\n",
    6158            name, instance->list_head, instance->list_head_pa);
    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-0x%0" PRIx32 "): %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

    r380e0364 re1dbcbc  
    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

    r380e0364 re1dbcbc  
    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,
    106113            BANDWIDTH_AVAILABLE_USB11);
    107114        CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
    108             ret, str_error(ret));
     115            str_error(ret));
    109116
    110117        hc_gain_control(instance);
    111118        ret = hc_init_memory(instance);
    112         CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures:%s.\n",
    113             ret, str_error(ret));
     119        CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: %s.\n",
     120            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-%#" PRIx32 " (%p).\n", instance->hcca,
     297                    instance->registers->hcca,
     298                    (void *) addr_to_phys(instance->hcca));
     299                usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
     300                    instance->registers->periodic_current);
     301
     302                link_t *current = instance->pending_batches.next;
     303                while (current != &instance->pending_batches) {
     304                        link_t *next = current->next;
     305                        usb_transfer_batch_t *batch =
     306                            usb_transfer_batch_from_link(current);
     307
     308                        if (batch_is_complete(batch)) {
     309                                list_remove(current);
     310                                usb_transfer_batch_finish(batch);
     311                        }
     312                        current = next;
     313                }
     314                fibril_mutex_unlock(&instance->guard);
    182315        }
    183316}
     
    191324                instance->registers->interrupt_status = status;
    192325                hc_interrupt(instance, status);
    193                 async_usleep(1000);
     326                async_usleep(50000);
    194327        }
    195328        return EOK;
     
    267400            instance->registers->control);
    268401
     402        /* Use HCCA */
     403        instance->registers->hcca = addr_to_phys(instance->hcca);
     404
     405        /* Use queues */
     406        instance->registers->bulk_head =
     407            instance->lists[USB_TRANSFER_BULK].list_head_pa;
     408        usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
     409            instance->lists[USB_TRANSFER_BULK].list_head,
     410            instance->lists[USB_TRANSFER_BULK].list_head_pa);
     411
     412        instance->registers->control_head =
     413            instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
     414        usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
     415            instance->lists[USB_TRANSFER_CONTROL].list_head,
     416            instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
     417
    269418        /* Enable queues */
    270419        instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
     
    296445        assert(instance);
    297446
    298 #define SETUP_TRANSFER_LIST(type, name) \
     447#define SETUP_ENDPOINT_LIST(type) \
    299448do { \
    300         int ret = transfer_list_init(&instance->type, name); \
     449        const char *name = usb_str_transfer_type(type); \
     450        int ret = endpoint_list_init(&instance->lists[type], name); \
    301451        if (ret != EOK) { \
    302                 usb_log_error("Failed(%d) to setup %s transfer list.\n", \
     452                usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
    303453                    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); \
     454                endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \
     455                endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
     456                endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \
     457                endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \
    308458        } \
    309459} while (0)
    310460
    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
     461        SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS);
     462        SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT);
     463        SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL);
     464        SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK);
     465#undef SETUP_ENDPOINT_LIST
     466        endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT],
     467            &instance->lists[USB_TRANSFER_ISOCHRONOUS]);
     468
     469        return EOK;
    331470}
    332471/*----------------------------------------------------------------------------*/
     
    342481                return ENOMEM;
    343482        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);
     483        usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
    359484
    360485        unsigned i = 0;
    361486        for (; i < 32; ++i) {
    362487                instance->hcca->int_ep[i] =
    363                     instance->transfers_interrupt.list_head_pa;
    364         }
    365         usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
    366             instance->transfers_interrupt.list_head,
    367             instance->transfers_interrupt.list_head_pa);
     488                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
     489        }
     490        usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
     491            instance->lists[USB_TRANSFER_INTERRUPT].list_head,
     492            instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
    368493
    369494        return EOK;
  • uspace/drv/ohci/hc.h

    r380e0364 re1dbcbc  
    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

    r380e0364 re1dbcbc  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2011 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
     28/** @addtogroup drvusbohci
     29 * @{
     30 */
     31/** @file
     32 * @brief OHCI driver
     33 */
     34#ifndef DRV_OHCI_HCD_ENDPOINT_H
     35#define DRV_OHCI_HCD_ENDPOINT_H
    2836
    29 /** @addtogroup drvusbvhc
    30  * @{
    31  */
    32 /** @file
    33  * @brief Virtual device management.
    34  */
    35 #ifndef VHCD_DEVICES_H_
    36 #define VHCD_DEVICES_H_
     37#include <assert.h>
     38#include <adt/list.h>
    3739
    38 #include <adt/list.h>
    39 #include <usb/usb.h>
     40#include <usb/host/endpoint.h>
    4041
    41 #include "hc.h"
     42#include "hw_struct/endpoint_descriptor.h"
     43#include "hw_struct/transfer_descriptor.h"
    4244
    43 /** Connected virtual device. */
    44 typedef struct {
    45         /** Phone used when sending data to device. */
    46         int phone;
    47         /** Unique identification. */
    48         sysarg_t id;
    49         /** Linked-list handle. */
     45typedef struct hcd_endpoint {
     46        ed_t *ed;
     47        td_t *td;
    5048        link_t link;
    51 } virtdev_connection_t;
     49} hcd_endpoint_t;
    5250
    53 virtdev_connection_t *virtdev_add_device(int, sysarg_t);
    54 virtdev_connection_t *virtdev_find(sysarg_t);
    55 void virtdev_destroy_device(virtdev_connection_t *);
    56 int virtdev_send_to_all(transaction_t *);
     51hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep);
    5752
     53hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep);
     54
     55void hcd_endpoint_clear(endpoint_t *ep);
    5856#endif
    5957/**
  • uspace/drv/ohci/hw_struct/endpoint_descriptor.c

    r380e0364 re1dbcbc  
    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

    r380e0364 re1dbcbc  
    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
     
    7373#define ED_TDHEAD_ZERO_SHIFT (2)
    7474#define ED_TDHEAD_TOGGLE_CARRY (0x2)
     75#define ED_TDHEAD_HALTED_FLAG (0x1)
    7576
    7677        volatile uint32_t next;
     
    8182void ed_init(ed_t *instance, endpoint_t *ep);
    8283
    83 static inline void ed_add_tds(ed_t *instance, td_t *head, td_t *tail)
     84static inline void ed_set_td(ed_t *instance, td_t *td)
    8485{
    8586        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;
     87        uintptr_t pa = addr_to_phys(td);
     88        instance->td_head =
     89            ((pa & ED_TDHEAD_PTR_MASK)
     90            | (instance->td_head & ~ED_TDHEAD_PTR_MASK));
     91        instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
     92}
     93
     94static inline void ed_set_end_td(ed_t *instance, td_t *td)
     95{
     96        assert(instance);
     97        uintptr_t pa = addr_to_phys(td);
     98        instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
    8899}
    89100
     
    97108}
    98109
     110static inline int ed_toggle_get(ed_t *instance)
     111{
     112        assert(instance);
     113        return (instance->td_head & ED_TDHEAD_TOGGLE_CARRY) ? 1 : 0;
     114}
     115
     116static inline void ed_toggle_set(ed_t *instance, int toggle)
     117{
     118        assert(instance);
     119        assert(toggle == 0 || toggle == 1);
     120        if (toggle == 1) {
     121                instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
     122        } else {
     123                /* clear halted flag when reseting toggle */
     124                instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY;
     125                instance->td_head &= ~ED_TDHEAD_HALTED_FLAG;
     126        }
     127}
    99128#endif
    100129/**
  • uspace/drv/ohci/hw_struct/hcca.h

    r380e0364 re1dbcbc  
    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

    r380e0364 re1dbcbc  
    5252                instance->status |= togg[toggle] << TD_STATUS_T_SHIFT;
    5353        }
     54        if (dir == USB_DIRECTION_IN) {
     55                instance->status |= TD_STATUS_ROUND_FLAG;
     56        }
    5457        if (buffer != NULL) {
     58                assert(size != 0);
    5559                instance->cbp = addr_to_phys(buffer);
    5660                instance->be = addr_to_phys(buffer + size - 1);
  • uspace/drv/ohci/hw_struct/transfer_descriptor.h

    r380e0364 re1dbcbc  
    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)
     
    5959#define TD_STATUS_T_0 (0x2)
    6060#define TD_STATUS_T_1 (0x3)
     61#define TD_STATUS_T_ED (0)
    6162#define TD_STATUS_EC_MASK (0x3) /* error count */
    6263#define TD_STATUS_EC_SHIFT (26)
     
    8687        int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
    8788        /* something went wrong, error code is set */
    88         if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2 && cc != CC_NOERROR) {
     89        if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2) {
    8990                return true;
    9091        }
     
    102103        return cc_to_rc(cc);
    103104}
     105
     106static inline size_t td_remain_size(td_t *instance)
     107{
     108        assert(instance);
     109        if (instance->cbp == 0)
     110                return 0;
     111        return instance->be - instance->cbp + 1;
     112}
    104113#endif
    105114/**
  • uspace/drv/ohci/iface.c

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

    r380e0364 re1dbcbc  
    148148            pci_get_my_registers(device, &mem_reg_base, &mem_reg_size, &irq);
    149149        CHECK_RET_DEST_FUN_RETURN(ret,
    150             "Failed(%d) to get memory addresses:.\n", ret, device->handle);
    151         usb_log_debug("Memory mapped regs at 0x%X (size %zu), IRQ %d.\n",
    152             mem_reg_base, mem_reg_size, irq);
     150            "Failed to get memory addresses for %" PRIun ": %s.\n",
     151            device->handle, str_error(ret));
     152        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
     153            (void *) mem_reg_base, mem_reg_size, irq);
    153154
    154155        ret = pci_disable_legacy(device);
  • uspace/drv/ohci/ohci.ma

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

    r380e0364 re1dbcbc  
    5555#define C_HCFS_MASK        (0x3) /* Host controller functional state */
    5656#define C_HCFS_RESET       (0x0)
    57 #define C_HCFS_OPERATIONAL (0x1)
    58 #define C_HCFS_RESUME      (0x2)
     57#define C_HCFS_RESUME      (0x1)
     58#define C_HCFS_OPERATIONAL (0x2)
    5959#define C_HCFS_SUSPEND     (0x3)
    6060#define C_HCFS_SHIFT       (6)
     
    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/pci.c

    r380e0364 re1dbcbc  
    117117                                mem_address = res->res.mem_range.address;
    118118                                mem_size = res->res.mem_range.size;
    119                                 usb_log_debug2("Found mem: %llx %zu.\n",
    120                                     mem_address, mem_size);
     119                                usb_log_debug2("Found mem: %p %zu.\n",
     120                                    (void *) mem_address, mem_size);
    121121                                mem_found = true;
    122122                                }
  • uspace/drv/ohci/root_hub.c

    r380e0364 re1dbcbc  
    149149
    150150
    151 static void usb_create_serialized_hub_descriptor(rh_t *instance,
    152         uint8_t ** out_result,
    153         size_t * out_size);
    154 
    155 static void rh_init_descriptors(rh_t *instance);
     151static int create_serialized_hub_descriptor(rh_t *instance);
     152
     153static int rh_init_descriptors(rh_t *instance);
    156154
    157155static int process_get_port_status_request(rh_t *instance, uint16_t port,
     
    164162        usb_transfer_batch_t * request);
    165163
    166 static void create_interrupt_mask(rh_t *instance, void ** buffer,
    167         size_t * buffer_size);
     164static void create_interrupt_mask_in_instance(rh_t *instance);
    168165
    169166static int process_get_descriptor_request(rh_t *instance,
     
    198195static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
    199196
    200 
     197static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request);
     198
     199static bool is_zeros(void * buffer, size_t size);
    201200
    202201
     
    205204 * @return Error code.
    206205 */
    207 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs) {
     206int rh_init(rh_t *instance, ohci_regs_t *regs) {
    208207        assert(instance);
    209         //instance->address = -1;
    210208        instance->registers = regs;
    211         instance->device = dev;
    212209        instance->port_count =
    213210            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
    214         rh_init_descriptors(instance);
     211        int opResult = rh_init_descriptors(instance);
     212        if(opResult != EOK){
     213                return opResult;
     214        }
    215215        // set port power mode to no-power-switching
    216         instance->registers->rh_desc_a =
    217                 instance->registers->rh_desc_a | (1<<9);
     216        instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
     217        instance->unfinished_interrupt_transfer = NULL;
     218        instance->interrupt_mask_size = (instance->port_count + 8)/8;
     219        instance->interrupt_buffer = malloc(instance->interrupt_mask_size);
     220        if(!instance->interrupt_buffer)
     221                return ENOMEM;
     222       
    218223
    219224        usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
    220 
    221         //start generic usb hub driver
    222 
    223         /* TODO: implement */
    224225        return EOK;
    225226}
     
    237238        assert(request);
    238239        int opResult;
    239         if (request->transfer_type == USB_TRANSFER_CONTROL) {
     240        if (request->ep->transfer_type == USB_TRANSFER_CONTROL) {
    240241                usb_log_info("Root hub got CONTROL packet\n");
    241242                opResult = process_ctrl_request(instance, request);
    242         } else if (request->transfer_type == USB_TRANSFER_INTERRUPT) {
     243                usb_transfer_batch_finish_error(request, opResult);
     244        } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
    243245                usb_log_info("Root hub got INTERRUPT packet\n");
    244                 void * buffer;
    245                 create_interrupt_mask(instance, &buffer,
    246                         &(request->transfered_size));
    247                 memcpy(request->transport_buffer, buffer,
    248                         request->transfered_size);
     246                create_interrupt_mask_in_instance(instance);
     247                if(is_zeros(instance->interrupt_buffer,
     248                    instance->interrupt_mask_size)){
     249                        usb_log_debug("no changes..\n");
     250                        instance->unfinished_interrupt_transfer = request;
     251                        //will be finished later
     252                }else{
     253                        usb_log_debug("processing changes..\n");
     254                        process_interrupt_mask_in_instance(instance, request);
     255                }
    249256                opResult = EOK;
    250257        } else {
    251258                opResult = EINVAL;
    252         }
    253         usb_transfer_batch_finish_error(request, opResult);
    254         return EOK;
    255 }
    256 
    257 /*----------------------------------------------------------------------------*/
    258 
    259 
     259                usb_transfer_batch_finish_error(request, opResult);
     260        }
     261        return EOK;
     262}
     263
     264/*----------------------------------------------------------------------------*/
     265
     266/**
     267 * process interrupt on a hub
     268 *
     269 * If there is no pending interrupt transfer, nothing happens.
     270 * @param instance
     271 */
    260272void rh_interrupt(rh_t *instance) {
    261         usb_log_info("Whoa whoa wait, I`m not supposed to receive any "
    262                 "interrupts, am I?\n");
    263         /* TODO: implement? */
     273        if(!instance->unfinished_interrupt_transfer){
     274                return;
     275        }
     276        usb_log_debug("finalizing interrupt transfer\n");
     277        create_interrupt_mask_in_instance(instance);
     278        process_interrupt_mask_in_instance(instance,
     279            instance->unfinished_interrupt_transfer);
    264280}
    265281/*----------------------------------------------------------------------------*/
     
    272288 *
    273289 * @param instance root hub instance
    274  * @param@out out_result pointer to resultant serialized descriptor
    275  * @param@out out_size size of serialized descriptor
    276  */
    277 static void usb_create_serialized_hub_descriptor(rh_t *instance,
    278         uint8_t ** out_result,
    279         size_t * out_size) {
    280         //base size
    281         size_t size = 7;
    282         //variable size according to port count
    283         size_t var_size = instance->port_count / 8 +
    284                 ((instance->port_count % 8 > 0) ? 1 : 0);
    285         size += 2 * var_size;
     290 * @return error code
     291 */
     292static int create_serialized_hub_descriptor(rh_t *instance) {
     293        size_t size = 7 +
     294            ((instance->port_count +7 )/ 8) * 2;
     295        size_t var_size = (instance->port_count +7 )/ 8;
    286296        uint8_t * result = (uint8_t*) malloc(size);
     297        if(!result) return ENOMEM;
     298
    287299        bzero(result, size);
    288300        //size
     
    313325                result[7 + var_size + i] = 255;
    314326        }
    315         (*out_result) = result;
    316         (*out_size) = size;
     327        instance->hub_descriptor = result;
     328        instance->descriptor_size = size;
     329        return EOK;
    317330}
    318331/*----------------------------------------------------------------------------*/
     
    323336 * be initialized only once per hub.
    324337 * @instance root hub instance
    325  */
    326 static void rh_init_descriptors(rh_t *instance) {
     338 * @return error code
     339 */
     340static int rh_init_descriptors(rh_t *instance) {
    327341        memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
    328342                sizeof (ohci_rh_device_descriptor)
     
    331345        memcpy(&descriptor, &ohci_rh_conf_descriptor,
    332346                sizeof (ohci_rh_conf_descriptor));
    333         uint8_t * hub_descriptor;
    334         size_t hub_desc_size;
    335         usb_create_serialized_hub_descriptor(instance, &hub_descriptor,
    336                 &hub_desc_size);
    337 
     347
     348        int opResult = create_serialized_hub_descriptor(instance);
     349        if(opResult != EOK){
     350                return opResult;
     351        }
    338352        descriptor.total_length =
    339353                sizeof (usb_standard_configuration_descriptor_t) +
    340354                sizeof (usb_standard_endpoint_descriptor_t) +
    341355                sizeof (usb_standard_interface_descriptor_t) +
    342                 hub_desc_size;
     356                instance->descriptor_size;
    343357
    344358        uint8_t * full_config_descriptor =
    345359                (uint8_t*) malloc(descriptor.total_length);
     360        if(!full_config_descriptor){
     361                return ENOMEM;
     362        }
    346363        memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
    347364        memcpy(full_config_descriptor + sizeof (descriptor),
     
    353370                sizeof (ohci_rh_iface_descriptor) +
    354371                sizeof (ohci_rh_ep_descriptor),
    355                 hub_descriptor, hub_desc_size);
    356 
     372                instance->hub_descriptor, instance->descriptor_size);
     373       
    357374        instance->descriptors.configuration = full_config_descriptor;
    358375        instance->descriptors.configuration_size = descriptor.total_length;
     376        return EOK;
    359377}
    360378/*----------------------------------------------------------------------------*/
     
    374392        if (port < 1 || port > instance->port_count)
    375393                return EINVAL;
    376         uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;
     394        uint32_t * uint32_buffer = (uint32_t*) request->data_buffer;
    377395        request->transfered_size = 4;
    378396        uint32_buffer[0] = instance->registers->rh_port_status[port - 1];
     
    400418static int process_get_hub_status_request(rh_t *instance,
    401419        usb_transfer_batch_t * request) {
    402         uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;
     420        uint32_t * uint32_buffer = (uint32_t*) request->data_buffer;
    403421        request->transfered_size = 4;
    404422        //bits, 0,1,16,17
     
    447465 * bit i indicates change on i`th port (i>0). For more info see
    448466 * Hub and Port status bitmap specification in USB specification
    449  * (chapter 11.13.4)
    450  * @param instance root hub instance
    451  * @param@out buffer pointer to created interrupt mas
    452  * @param@out buffer_size size of created interrupt mask
    453  */
    454 static void create_interrupt_mask(rh_t *instance, void ** buffer,
    455         size_t * buffer_size) {
    456         int bit_count = instance->port_count + 1;
    457         (*buffer_size) = (bit_count / 8) + ((bit_count % 8 == 0) ? 0 : 1);
    458 
    459         (*buffer) = malloc(*buffer_size);
    460         uint8_t * bitmap = (uint8_t*) (*buffer);
     467 * (chapter 11.13.4).
     468 * Uses instance`s interrupt buffer to store the interrupt information.
     469 * @param instance root hub instance
     470 */
     471static void create_interrupt_mask_in_instance(rh_t * instance) {
     472        uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer);
    461473        uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
    462474                | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
    463         bzero(bitmap, (*buffer_size));
     475        bzero(bitmap, instance->interrupt_mask_size);
    464476        if (instance->registers->rh_status & mask) {
    465477                bitmap[0] = 1;
     
    492504        const uint16_t setup_request_value = setup_request->value_high;
    493505        //(setup_request->value_low << 8);
    494         bool del = false;
    495506        switch (setup_request_value) {
    496507                case USB_DESCTYPE_HUB:
    497508                {
    498                         uint8_t * descriptor;
    499                         usb_create_serialized_hub_descriptor(
    500                                 instance, &descriptor, &size);
    501                         result_descriptor = descriptor;
    502                         if (result_descriptor) del = true;
     509                        usb_log_debug("USB_DESCTYPE_HUB\n");
     510                        result_descriptor = instance->hub_descriptor;
     511                        size = instance->descriptor_size;
    503512                        break;
    504513                }
     
    550559        }
    551560        request->transfered_size = size;
    552         memcpy(request->transport_buffer, result_descriptor, size);
    553         if (del)
    554                 free(result_descriptor);
     561        memcpy(request->data_buffer, result_descriptor, size);
    555562        return EOK;
    556563}
     
    571578        if (request->buffer_size != 1)
    572579                return EINVAL;
    573         request->transport_buffer[0] = 1;
     580        request->data_buffer[0] = 1;
    574581        request->transfered_size = 1;
    575582        return EOK;
     
    866873        return opResult;
    867874}
     875/*----------------------------------------------------------------------------*/
     876
     877/**
     878 * process hanging interrupt request
     879 *
     880 * If an interrupt transfer has been received and there was no change,
     881 * the driver stores the transfer information and waits for change to occcur.
     882 * This routine is called when that happens and it finalizes the interrupt
     883 * transfer.
     884 *
     885 * @param instance hub instance
     886 * @param request batch request to be processed
     887 *
     888 * @return
     889 */
     890static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request){
     891        memcpy(request->data_buffer, instance->interrupt_buffer,
     892            instance->interrupt_mask_size);
     893        request->transfered_size = instance->interrupt_mask_size;
     894        instance->unfinished_interrupt_transfer = NULL;
     895        usb_transfer_batch_finish_error(request, EOK);
     896        return EOK;
     897}
     898
     899/*----------------------------------------------------------------------------*/
     900
     901/**
     902 * return whether the buffer is full of zeros
     903 *
     904 * Convenience function.
     905 * @param buffer
     906 * @param size
     907 * @return
     908 */
     909static bool is_zeros(void * buffer, size_t size){
     910        if(!buffer) return true;
     911        if(!size) return true;
     912        size_t i;
     913        for(i=0;i<size;++i){
     914                if(((char*)buffer)[i])
     915                        return false;
     916        }
     917        return true;
     918}
    868919
    869920/**
  • uspace/drv/ohci/root_hub.h

    r380e0364 re1dbcbc  
    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;
    5654        /** hubs descriptors */
    5755        usb_device_descriptors_t descriptors;
     56        /** interrupt transfer waiting for an actual interrupt to occur */
     57        usb_transfer_batch_t * unfinished_interrupt_transfer;
     58        /** pre-allocated interrupt mask
     59         *
     60         * This is allocated when initializing instance, so that memory
     61         * allocation is not needed when processing request. Buffer is used for
     62         * interrupt bitmask.
     63         */
     64        uint8_t * interrupt_buffer;
     65        /** size of interrupt buffer */
     66        size_t interrupt_mask_size;
     67        /** instance`s descriptor*/
     68        uint8_t * hub_descriptor;
     69        /** size of hub descriptor */
     70        size_t descriptor_size;
     71
     72
    5873} rh_t;
    5974
    60 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs);
     75int rh_init(rh_t *instance, ohci_regs_t *regs);
    6176
    6277int rh_request(rh_t *instance, usb_transfer_batch_t *request);
  • uspace/drv/ohci/utils/malloc32.h

    r380e0364 re1dbcbc  
    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
Note: See TracChangeset for help on using the changeset viewer.