Changeset 8c877b2 in mainline for uspace/drv/uhci-hcd


Ignore:
Timestamp:
2011-03-04T13:05:35Z (15 years ago)
Author:
Matus Dekanek <smekideki@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/fix-logger-deadlock, topic/msim-upgrade, topic/simplify-dev-export
Children:
d49728c
Parents:
dff940f8 (diff), 9a422574 (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 with \usb\development

Location:
uspace/drv/uhci-hcd
Files:
2 added
15 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/uhci-hcd/Makefile

    rdff940f8 r8c877b2  
    3939        uhci.c \
    4040        uhci_struct/transfer_descriptor.c \
     41        utils/device_keeper.c \
    4142        pci.c \
    4243        batch.c
  • uspace/drv/uhci-hcd/batch.c

    rdff940f8 r8c877b2  
    3333 */
    3434#include <errno.h>
    35 
     35#include <str_error.h>
     36
     37#include <usb/usb.h>
    3638#include <usb/debug.h>
    3739
     
    4547static int batch_schedule(batch_t *instance);
    4648
     49static void batch_control(
     50    batch_t *instance, int data_stage, int status_stage);
    4751static void batch_call_in(batch_t *instance);
    4852static void batch_call_out(batch_t *instance);
     
    5357batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    5458    usb_transfer_type_t transfer_type, size_t max_packet_size,
    55     dev_speed_t speed, char *buffer, size_t size,
     59    usb_speed_t speed, char *buffer, size_t size,
    5660    char* setup_buffer, size_t setup_size,
    5761    usbhc_iface_transfer_in_callback_t func_in,
     
    9296        instance->transport_buffer =
    9397           (size > 0) ? malloc32(transport_size) : NULL;
     98
    9499        if ((size > 0) && (instance->transport_buffer == NULL)) {
    95100                usb_log_error("Failed to allocate device accessible buffer.\n");
     
    133138
    134139        queue_head_element_td(instance->qh, addr_to_phys(instance->tds));
     140        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
     141            instance, target.address, target.endpoint);
    135142        return instance;
    136143}
     
    139146{
    140147        assert(instance);
    141         usb_log_debug("Checking(%p) %d packet for completion.\n",
     148        usb_log_debug2("Batch(%p) checking %d packet(s) for completion.\n",
    142149            instance, instance->packets);
    143150        instance->transfered_size = 0;
     
    151158                        if (i > 0)
    152159                                instance->transfered_size -= instance->setup_size;
     160                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
     161                          instance, i, instance->tds[i].status);
    153162                        return true;
    154163                }
     
    156165                    transfer_descriptor_actual_size(&instance->tds[i]);
    157166        }
    158         /* This is just an ugly trick to support the old API */
    159167        instance->transfered_size -= instance->setup_size;
    160168        return true;
     
    164172{
    165173        assert(instance);
    166 
    167174        /* we are data out, we are supposed to provide data */
    168175        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    169 
    170         int toggle = 0;
    171         /* setup stage */
    172         transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
    173             instance->setup_size, toggle, false, instance->target,
    174             USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
    175 
    176         /* data stage */
    177         size_t i = 1;
    178         for (;i < instance->packets - 1; ++i) {
    179                 char *data =
    180                     instance->transport_buffer + ((i - 1) * instance->max_packet_size);
    181                 toggle = 1 - toggle;
    182 
    183                 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    184                     instance->max_packet_size, toggle++, false, instance->target,
    185                     USB_PID_OUT, data, &instance->tds[i + 1]);
    186         }
    187 
    188         /* status stage */
    189         i = instance->packets - 1;
    190         transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    191             0, 1, false, instance->target, USB_PID_IN, NULL, NULL);
    192 
    193         instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    194 
     176        batch_control(instance, USB_PID_OUT, USB_PID_IN);
    195177        instance->next_step = batch_call_out_and_dispose;
     178        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    196179        batch_schedule(instance);
    197180}
     
    200183{
    201184        assert(instance);
    202 
    203         int toggle = 0;
    204         /* setup stage */
    205         transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
    206             instance->setup_size, toggle, false, instance->target,
    207             USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
    208 
    209         /* data stage */
    210         size_t i = 1;
    211         for (;i < instance->packets - 1; ++i) {
    212                 char *data =
    213                     instance->transport_buffer + ((i - 1) * instance->max_packet_size);
    214                 toggle = 1 - toggle;
    215 
    216                 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    217                     instance->max_packet_size, toggle, false, instance->target,
    218                     USB_PID_IN, data, &instance->tds[i + 1]);
    219         }
    220 
    221         /* status stage */
    222         i = instance->packets - 1;
    223         transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    224             0, 1, false, instance->target, USB_PID_OUT, NULL, NULL);
    225 
    226         instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    227 
     185        batch_control(instance, USB_PID_IN, USB_PID_OUT);
    228186        instance->next_step = batch_call_in_and_dispose;
     187        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    229188        batch_schedule(instance);
    230189}
     
    234193        assert(instance);
    235194
     195        const bool low_speed = instance->speed == USB_SPEED_LOW;
    236196        int toggle = 1;
    237197        size_t i = 0;
     
    244204
    245205                transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    246                     instance->max_packet_size, toggle, false, instance->target,
    247                     USB_PID_IN, data, next);
     206                    instance->max_packet_size, toggle, false, low_speed,
     207                    instance->target, USB_PID_IN, data, next);
    248208        }
    249209
     
    251211
    252212        instance->next_step = batch_call_in_and_dispose;
     213        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    253214        batch_schedule(instance);
    254215}
     
    257218{
    258219        assert(instance);
    259 
    260220        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    261221
     222        const bool low_speed = instance->speed == USB_SPEED_LOW;
    262223        int toggle = 1;
    263224        size_t i = 0;
     
    270231
    271232                transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
    272                     instance->max_packet_size, toggle++, false, instance->target,
    273                     USB_PID_OUT, data, next);
     233                    instance->max_packet_size, toggle++, false, low_speed,
     234                    instance->target, USB_PID_OUT, data, next);
    274235        }
    275236
     
    277238
    278239        instance->next_step = batch_call_out_and_dispose;
     240        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    279241        batch_schedule(instance);
    280242}
    281243/*----------------------------------------------------------------------------*/
     244static void batch_control(
     245    batch_t *instance, int data_stage, int status_stage)
     246{
     247        assert(instance);
     248
     249        const bool low_speed = instance->speed == USB_SPEED_LOW;
     250        int toggle = 0;
     251        /* setup stage */
     252        transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
     253            instance->setup_size, toggle, false, low_speed, instance->target,
     254            USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
     255
     256        /* data stage */
     257        size_t packet = 1;
     258        size_t remain_size = instance->buffer_size;
     259        while (remain_size > 0) {
     260                char *data =
     261                    instance->transport_buffer + instance->buffer_size
     262                    - remain_size;
     263
     264                toggle = 1 - toggle;
     265
     266                const size_t packet_size =
     267                    (instance->max_packet_size > remain_size) ?
     268                    remain_size : instance->max_packet_size;
     269
     270                transfer_descriptor_init(&instance->tds[packet],
     271                    DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,
     272                    instance->target, data_stage, data,
     273                    &instance->tds[packet + 1]);
     274
     275                ++packet;
     276                assert(packet < instance->packets);
     277                assert(packet_size <= remain_size);
     278                remain_size -= packet_size;
     279        }
     280
     281        /* status stage */
     282        assert(packet == instance->packets - 1);
     283        transfer_descriptor_init(&instance->tds[packet], DEFAULT_ERROR_COUNT,
     284            0, 1, false, low_speed, instance->target, status_stage, NULL, NULL);
     285
     286
     287        instance->tds[packet].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
     288        usb_log_debug2("Control last TD status: %x.\n",
     289            instance->tds[packet].status);
     290}
     291/*----------------------------------------------------------------------------*/
    282292void batch_call_in(batch_t *instance)
    283293{
     
    288298
    289299        int err = instance->error;
    290         usb_log_info("Callback IN(%d): %d, %zu.\n", instance->transfer_type,
    291             err, instance->transfered_size);
     300        usb_log_debug("Batch(%p) callback IN(type:%d): %s(%d), %zu.\n",
     301            instance, instance->transfer_type, str_error(err), err,
     302            instance->transfered_size);
    292303
    293304        instance->callback_in(instance->fun,
     
    302313
    303314        int err = instance->error;
    304         usb_log_info("Callback OUT(%d): %d.\n", instance->transfer_type, err);
     315        usb_log_debug("Batch(%p) callback OUT(type:%d): %s(%d).\n",
     316            instance, instance->transfer_type, str_error(err), err);
    305317        instance->callback_out(instance->fun,
    306318            err, instance->arg);
     
    311323        assert(instance);
    312324        batch_call_in(instance);
    313         usb_log_debug("Disposing batch: %p.\n", instance);
     325        usb_log_debug("Batch(%p) disposing.\n", instance);
    314326        free32(instance->tds);
    315327        free32(instance->qh);
     
    323335        assert(instance);
    324336        batch_call_out(instance);
    325         usb_log_debug("Disposing batch: %p.\n", instance);
     337        usb_log_debug("Batch(%p) disposing.\n", instance);
    326338        free32(instance->tds);
    327339        free32(instance->qh);
     
    338350        return uhci_schedule(hc, instance);
    339351}
    340 /*----------------------------------------------------------------------------*/
    341 /* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
    342 void batch_control_setup_old(batch_t *instance)
    343 {
    344         assert(instance);
    345         instance->packets = 1;
    346 
    347         /* setup stage */
    348         transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
    349             instance->setup_size, 0, false, instance->target,
    350             USB_PID_SETUP, instance->setup_buffer, NULL);
    351 
    352         instance->next_step = batch_call_out_and_dispose;
    353         batch_schedule(instance);
    354 }
    355 /*----------------------------------------------------------------------------*/
    356 void batch_control_write_data_old(batch_t *instance)
    357 {
    358         assert(instance);
    359         instance->packets -= 2;
    360         batch_interrupt_out(instance);
    361 }
    362 /*----------------------------------------------------------------------------*/
    363 void batch_control_read_data_old(batch_t *instance)
    364 {
    365         assert(instance);
    366         instance->packets -= 2;
    367         batch_interrupt_in(instance);
    368 }
    369 /*----------------------------------------------------------------------------*/
    370 void batch_control_write_status_old(batch_t *instance)
    371 {
    372         assert(instance);
    373         instance->packets = 1;
    374         transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
    375             0, 1, false, instance->target, USB_PID_IN, NULL, NULL);
    376         instance->next_step = batch_call_in_and_dispose;
    377         batch_schedule(instance);
    378 }
    379 /*----------------------------------------------------------------------------*/
    380 void batch_control_read_status_old(batch_t *instance)
    381 {
    382         assert(instance);
    383         instance->packets = 1;
    384         transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
    385             0, 1, false, instance->target, USB_PID_OUT, NULL, NULL);
    386         instance->next_step = batch_call_out_and_dispose;
    387         batch_schedule(instance);
    388 }
    389352/**
    390353 * @}
  • uspace/drv/uhci-hcd/batch.h

    rdff940f8 r8c877b2  
    4343#include "uhci_struct/queue_head.h"
    4444
    45 typedef enum {
    46         LOW_SPEED,
    47         FULL_SPEED,
    48 } dev_speed_t;
    49 
    5045typedef struct batch
    5146{
    5247        link_t link;
    53         dev_speed_t speed;
     48        usb_speed_t speed;
    5449        usb_target_t target;
    5550        usb_transfer_type_t transfer_type;
     
    7671batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    7772    usb_transfer_type_t transfer_type, size_t max_packet_size,
    78     dev_speed_t speed, char *buffer, size_t size,
     73    usb_speed_t speed, char *buffer, size_t size,
    7974                char *setup_buffer, size_t setup_size,
    8075    usbhc_iface_transfer_in_callback_t func_in,
  • uspace/drv/uhci-hcd/iface.c

    rdff940f8 r8c877b2  
    4141#include "iface.h"
    4242#include "uhci.h"
     43#include "utils/device_keeper.h"
    4344
    4445/*----------------------------------------------------------------------------*/
     
    4849        uhci_t *hc = fun_to_uhci(fun);
    4950        assert(hc);
    50         usb_address_keeping_reserve_default(&hc->address_manager);
     51        usb_log_debug("Default address request with speed %d.\n", speed);
     52        device_keeper_reserve_default(&hc->device_manager, speed);
    5153        return EOK;
    5254}
     
    5759        uhci_t *hc = fun_to_uhci(fun);
    5860        assert(hc);
    59         usb_address_keeping_release_default(&hc->address_manager);
     61        usb_log_debug("Default address release.\n");
     62        device_keeper_release_default(&hc->device_manager);
    6063        return EOK;
    6164}
     
    6770        uhci_t *hc = fun_to_uhci(fun);
    6871        assert(hc);
    69         *address = usb_address_keeping_request(&hc->address_manager);
     72        assert(address);
     73
     74        usb_log_debug("Address request with speed %d.\n", speed);
     75        *address = device_keeper_request(&hc->device_manager, speed);
     76        usb_log_debug("Address request with result: %d.\n", *address);
    7077        if (*address <= 0)
    7178          return *address;
     
    7986        uhci_t *hc = fun_to_uhci(fun);
    8087        assert(hc);
    81         usb_address_keeping_devman_bind(&hc->address_manager, address, handle);
     88        usb_log_debug("Address bind %d-%d.\n", address, handle);
     89        device_keeper_bind(&hc->device_manager, address, handle);
    8290        return EOK;
    8391}
     
    8896        uhci_t *hc = fun_to_uhci(fun);
    8997        assert(hc);
    90         usb_address_keeping_release_default(&hc->address_manager);
     98        usb_log_debug("Address release %d.\n", address);
     99        device_keeper_release(&hc->device_manager, address);
    91100        return EOK;
    92101}
    93102/*----------------------------------------------------------------------------*/
    94103static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
    95     size_t max_packet_size,
    96     void *data, size_t size,
     104    size_t max_packet_size, void *data, size_t size,
    97105    usbhc_iface_transfer_out_callback_t callback, void *arg)
    98106{
    99         dev_speed_t speed = FULL_SPEED;
     107        assert(fun);
     108        uhci_t *hc = fun_to_uhci(fun);
     109        assert(hc);
     110        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     111
     112        usb_log_debug("Interrupt OUT %d:%d %zu(%zu).\n",
     113            target.address, target.endpoint, size, max_packet_size);
    100114
    101115        batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
     
    108122/*----------------------------------------------------------------------------*/
    109123static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
    110     size_t max_packet_size,
    111     void *data, size_t size,
     124    size_t max_packet_size, void *data, size_t size,
    112125    usbhc_iface_transfer_in_callback_t callback, void *arg)
    113126{
    114         dev_speed_t speed = FULL_SPEED;
     127        assert(fun);
     128        uhci_t *hc = fun_to_uhci(fun);
     129        assert(hc);
     130        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     131        usb_log_debug("Interrupt IN %d:%d %zu(%zu).\n",
     132            target.address, target.endpoint, size, max_packet_size);
    115133
    116134        batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
     
    127145    usbhc_iface_transfer_out_callback_t callback, void *arg)
    128146{
    129         dev_speed_t speed = FULL_SPEED;
     147        assert(fun);
     148        uhci_t *hc = fun_to_uhci(fun);
     149        assert(hc);
     150        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     151        usb_log_debug("Control WRITE %d:%d %zu(%zu).\n",
     152            target.address, target.endpoint, size, max_packet_size);
    130153
    131154        batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
     
    143166    usbhc_iface_transfer_in_callback_t callback, void *arg)
    144167{
    145         dev_speed_t speed = FULL_SPEED;
    146 
     168        assert(fun);
     169        uhci_t *hc = fun_to_uhci(fun);
     170        assert(hc);
     171        usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
     172
     173        usb_log_debug("Control READ %d:%d %zu(%zu).\n",
     174            target.address, target.endpoint, size, max_packet_size);
    147175        batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
    148176            max_packet_size, speed, data, size, setup_data, setup_size, callback,
  • uspace/drv/uhci-hcd/main.c

    rdff940f8 r8c877b2  
    3434#include <ddf/driver.h>
    3535#include <ddf/interrupt.h>
     36#include <device/hw_res.h>
     37#include <errno.h>
     38#include <str_error.h>
     39
    3640#include <usb_iface.h>
    3741#include <usb/ddfiface.h>
    38 #include <device/hw_res.h>
    39 
    40 #include <errno.h>
    41 
    4242#include <usb/debug.h>
    4343
     
    5050
    5151static int uhci_add_device(ddf_dev_t *device);
    52 
    5352/*----------------------------------------------------------------------------*/
    5453static driver_ops_t uhci_driver_ops = {
     
    7069}
    7170/*----------------------------------------------------------------------------*/
    72 #define CHECK_RET_RETURN(ret, message...) \
     71static int uhci_add_device(ddf_dev_t *device)
     72{
     73        assert(device);
     74        uhci_t *hcd = NULL;
     75#define CHECK_RET_FREE_HC_RETURN(ret, message...) \
    7376if (ret != EOK) { \
    7477        usb_log_error(message); \
     78        if (hcd != NULL) \
     79                free(hcd); \
    7580        return ret; \
    7681}
    7782
    78 static int uhci_add_device(ddf_dev_t *device)
    79 {
    80         assert(device);
    81 
    8283        usb_log_info("uhci_add_device() called\n");
    8384
    84 
    85         uintptr_t io_reg_base;
    86         size_t io_reg_size;
    87         int irq;
     85        uintptr_t io_reg_base = 0;
     86        size_t io_reg_size = 0;
     87        int irq = 0;
    8888
    8989        int ret =
    9090            pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
    91 
    92         CHECK_RET_RETURN(ret,
     91        CHECK_RET_FREE_HC_RETURN(ret,
    9392            "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
    9493        usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
    9594            io_reg_base, io_reg_size, irq);
    9695
     96        ret = pci_disable_legacy(device);
     97        CHECK_RET_FREE_HC_RETURN(ret,
     98            "Failed(%d) disable legacy USB: %s.\n", ret, str_error(ret));
     99
     100#if 0
    97101        ret = pci_enable_interrupts(device);
    98         CHECK_RET_RETURN(ret, "Failed(%d) to get enable interrupts:\n", ret);
     102        if (ret != EOK) {
     103                usb_log_warning(
     104                    "Failed(%d) to enable interrupts, fall back to polling.\n",
     105                    ret);
     106        }
     107#endif
    99108
    100         uhci_t *uhci_hc = malloc(sizeof(uhci_t));
    101         ret = (uhci_hc != NULL) ? EOK : ENOMEM;
    102         CHECK_RET_RETURN(ret, "Failed to allocate memory for uhci hcd driver.\n");
     109        hcd = malloc(sizeof(uhci_t));
     110        ret = (hcd != NULL) ? EOK : ENOMEM;
     111        CHECK_RET_FREE_HC_RETURN(ret,
     112            "Failed(%d) to allocate memory for uhci hcd.\n", ret);
    103113
    104         ret = uhci_init(uhci_hc, device, (void*)io_reg_base, io_reg_size);
    105         if (ret != EOK) {
    106                 usb_log_error("Failed to init uhci-hcd.\n");
    107                 free(uhci_hc);
    108                 return ret;
    109         }
     114        ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size);
     115        CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n",
     116            ret);
     117#undef CHECK_RET_FREE_HC_RETURN
    110118
    111119        /*
    112          * We might free uhci_hc, but that does not matter since no one
     120         * We might free hcd, but that does not matter since no one
    113121         * else would access driver_data anyway.
    114122         */
    115         device->driver_data = uhci_hc;
     123        device->driver_data = hcd;
    116124
     125        ddf_fun_t *rh = NULL;
     126#define CHECK_RET_FINI_FREE_RETURN(ret, message...) \
     127if (ret != EOK) { \
     128        usb_log_error(message); \
     129        if (hcd != NULL) {\
     130                uhci_fini(hcd); \
     131                free(hcd); \
     132        } \
     133        if (rh != NULL) \
     134                free(rh); \
     135        return ret; \
     136}
     137
     138        /* It does no harm if we register this on polling */
    117139        ret = register_interrupt_handler(device, irq, irq_handler,
    118             &uhci_hc->interrupt_code);
    119         if (ret != EOK) {
    120                 usb_log_error("Failed to register interrupt handler.\n");
    121                 uhci_fini(uhci_hc);
    122                 free(uhci_hc);
    123                 return ret;
    124         }
     140            &hcd->interrupt_code);
     141        CHECK_RET_FINI_FREE_RETURN(ret,
     142            "Failed(%d) to register interrupt handler.\n", ret);
    125143
    126         ddf_fun_t *rh;
    127144        ret = setup_root_hub(&rh, device);
    128         if (ret != EOK) {
    129                 usb_log_error("Failed to setup uhci root hub.\n");
    130                 uhci_fini(uhci_hc);
    131                 free(uhci_hc);
    132                 return ret;
    133         }
    134         rh->driver_data = uhci_hc->ddf_instance;
     145        CHECK_RET_FINI_FREE_RETURN(ret,
     146            "Failed(%d) to setup UHCI root hub.\n", ret);
     147        rh->driver_data = hcd->ddf_instance;
    135148
    136149        ret = ddf_fun_bind(rh);
    137         if (ret != EOK) {
    138                 usb_log_error("Failed to register root hub.\n");
    139                 uhci_fini(uhci_hc);
    140                 free(uhci_hc);
    141                 free(rh);
    142                 return ret;
    143         }
     150        CHECK_RET_FINI_FREE_RETURN(ret,
     151            "Failed(%d) to register UHCI root hub.\n", ret);
    144152
    145153        return EOK;
     154#undef CHECK_RET_FINI_FREE_RETURN
    146155}
    147156/*----------------------------------------------------------------------------*/
     
    149158{
    150159        sleep(3);
    151         usb_log_enable(USB_LOG_LEVEL_INFO, NAME);
     160        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    152161
    153162        return ddf_driver_main(&uhci_driver);
  • uspace/drv/uhci-hcd/pci.c

    rdff940f8 r8c877b2  
    3838#include <devman.h>
    3939#include <device/hw_res.h>
     40
     41#include <usb/debug.h>
     42#include <pci_dev_iface.h>
    4043
    4144#include "pci.h"
     
    8386                                irq = res->res.interrupt.irq;
    8487                                irq_found = true;
     88                                usb_log_debug2("Found interrupt: %d.\n", irq);
    8589                                break;
    8690                        case IO_RANGE:
    87                                 io_address = (uintptr_t)
    88                                     res->res.io_range.address;
     91                                io_address = res->res.io_range.address;
    8992                                io_size = res->res.io_range.size;
     93                                usb_log_debug2("Found io: %llx %zu.\n",
     94                                    res->res.io_range.address, res->res.io_range.size);
    9095                                io_found = true;
    9196                                break;
     
    105110        }
    106111
    107         if (io_reg_address != NULL) {
    108                 *io_reg_address = io_address;
    109         }
    110         if (io_reg_size != NULL) {
    111                 *io_reg_size = io_size;
    112         }
    113         if (irq_no != NULL) {
    114                 *irq_no = irq;
    115         }
     112        *io_reg_address = io_address;
     113        *io_reg_size = io_size;
     114        *irq_no = irq;
    116115
    117116        rc = EOK;
     
    127126            IPC_FLAG_BLOCKING);
    128127        bool enabled = hw_res_enable_interrupt(parent_phone);
     128        async_hangup(parent_phone);
    129129        return enabled ? EOK : EIO;
    130130}
     131/*----------------------------------------------------------------------------*/
     132int pci_disable_legacy(ddf_dev_t *device)
     133{
     134        assert(device);
     135        int parent_phone = devman_parent_device_connect(device->handle,
     136                IPC_FLAG_BLOCKING);
     137        if (parent_phone < 0) {
     138                return parent_phone;
     139        }
     140
     141        /* See UHCI design guide for these values,
     142         * write all WC bits in USB legacy register */
     143        sysarg_t address = 0xc0;
     144        sysarg_t value = 0x8f00;
     145
     146  int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     147            IPC_M_CONFIG_SPACE_WRITE_16, address, value);
     148        async_hangup(parent_phone);
     149
     150  return rc;
     151}
     152/*----------------------------------------------------------------------------*/
    131153/**
    132154 * @}
  • uspace/drv/uhci-hcd/pci.h

    rdff940f8 r8c877b2  
    4040int pci_get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
    4141int pci_enable_interrupts(ddf_dev_t *);
     42int pci_disable_legacy(ddf_dev_t *);
    4243
    4344#endif
  • uspace/drv/uhci-hcd/root_hub.c

    rdff940f8 r8c877b2  
    3434#include <assert.h>
    3535#include <errno.h>
     36#include <str_error.h>
    3637#include <stdio.h>
     38#include <ops/hw_res.h>
     39
    3740#include <usb_iface.h>
    3841#include <usb/debug.h>
     
    4144#include "uhci.h"
    4245
     46/*----------------------------------------------------------------------------*/
    4347static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun,
    4448    devman_handle_t *handle)
     
    5155        return EOK;
    5256}
    53 
     57/*----------------------------------------------------------------------------*/
    5458static int usb_iface_get_address_rh_impl(ddf_fun_t *fun, devman_handle_t handle,
    5559    usb_address_t *address)
     
    6165        assert(hc);
    6266
    63         usb_address_t addr = usb_address_keeping_find(&hc->address_manager,
     67        usb_address_t addr = device_keeper_find(&hc->device_manager,
    6468            handle);
    6569        if (addr < 0) {
     
    7377        return EOK;
    7478}
    75 
     79/*----------------------------------------------------------------------------*/
    7680usb_iface_t usb_iface_root_hub_fun_impl = {
    7781        .get_hc_handle = usb_iface_get_hc_handle_rh_impl,
    7882        .get_address = usb_iface_get_address_rh_impl
    7983};
     84/*----------------------------------------------------------------------------*/
     85static hw_resource_list_t *get_resource_list(ddf_fun_t *dev)
     86{
     87        assert(dev);
     88        ddf_fun_t *hc_ddf_instance = dev->driver_data;
     89        assert(hc_ddf_instance);
     90        uhci_t *hc = hc_ddf_instance->driver_data;
     91        assert(hc);
    8092
     93        //TODO: fix memory leak
     94        hw_resource_list_t *resource_list = malloc(sizeof(hw_resource_list_t));
     95        assert(resource_list);
     96        resource_list->count = 1;
     97        resource_list->resources = malloc(sizeof(hw_resource_t));
     98        assert(resource_list->resources);
     99        resource_list->resources[0].type = IO_RANGE;
     100        resource_list->resources[0].res.io_range.address =
     101            ((uintptr_t)hc->registers) + 0x10; // see UHCI design guide
     102        resource_list->resources[0].res.io_range.size = 4;
     103        resource_list->resources[0].res.io_range.endianness = LITTLE_ENDIAN;
     104
     105        return resource_list;
     106}
     107/*----------------------------------------------------------------------------*/
     108static hw_res_ops_t hw_res_iface = {
     109        .get_resource_list = get_resource_list,
     110        .enable_interrupt = NULL
     111};
     112/*----------------------------------------------------------------------------*/
    81113static ddf_dev_ops_t root_hub_ops = {
    82         .interfaces[USB_DEV_IFACE] = &usb_iface_root_hub_fun_impl
     114        .interfaces[USB_DEV_IFACE] = &usb_iface_root_hub_fun_impl,
     115        .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface
    83116};
    84 
    85117/*----------------------------------------------------------------------------*/
    86118int setup_root_hub(ddf_fun_t **fun, ddf_dev_t *hc)
    87119{
    88120        assert(fun);
     121        assert(hc);
    89122        int ret;
    90123
     
    105138        ret = ddf_fun_add_match_id(hub, match_str, 100);
    106139        if (ret != EOK) {
    107                 usb_log_error("Failed to add root hub match id.\n");
     140                usb_log_error("Failed(%d) to add root hub match id: %s\n",
     141                    ret, str_error(ret));
    108142                ddf_fun_destroy(hub);
    109                 return ENOMEM;
     143                return ret;
    110144        }
    111145
  • uspace/drv/uhci-hcd/transfer_list.c

    rdff940f8 r8c877b2  
    7070        assert(instance);
    7171        assert(batch);
     72        usb_log_debug2("Adding batch(%p) to queue %s.\n", batch, instance->name);
    7273
    7374        uint32_t pa = (uintptr_t)addr_to_phys(batch->qh);
     
    8384                list_append(&batch->link, &instance->batch_list);
    8485                instance->queue_head->element = pa;
    85                 usb_log_debug2("Added batch(%p) to queue %s first.\n",
     86                usb_log_debug("Batch(%p) added to queue %s first.\n",
    8687                        batch, instance->name);
    8788                fibril_mutex_unlock(&instance->guard);
     
    9697        queue_head_append_qh(last->qh, pa);
    9798        list_append(&batch->link, &instance->batch_list);
    98         usb_log_debug2("Added batch(%p) to queue %s last, first is %p.\n",
     99        usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n",
    99100                batch, instance->name, first );
    100101        fibril_mutex_unlock(&instance->guard);
     
    108109        assert(instance->queue_head);
    109110        assert(batch->qh);
     111        usb_log_debug2("Removing batch(%p) from queue %s.\n", batch, instance->name);
    110112
    111113        /* I'm the first one here */
    112114        if (batch->link.prev == &instance->batch_list) {
    113                 usb_log_debug("Removing batch %p was first, next element %x.\n",
    114                         batch, batch->qh->next_queue);
     115                usb_log_debug("Batch(%p) removed (FIRST) from queue %s, next element %x.\n",
     116                        batch, instance->name, batch->qh->next_queue);
    115117                instance->queue_head->element = batch->qh->next_queue;
    116118        } else {
    117                 usb_log_debug("Removing batch %p was NOT first, next element %x.\n",
    118                         batch, batch->qh->next_queue);
     119                usb_log_debug("Batch(%p) removed (NOT FIRST) from queue, next element %x.\n",
     120                        batch, instance->name, batch->qh->next_queue);
    119121                batch_t *prev = list_get_instance(batch->link.prev, batch_t, link);
    120122                prev->qh->next_queue = batch->qh->next_queue;
     
    123125}
    124126/*----------------------------------------------------------------------------*/
    125 void transfer_list_check(transfer_list_t *instance)
     127void transfer_list_remove_finished(transfer_list_t *instance)
    126128{
    127129        assert(instance);
     130
     131        LIST_INITIALIZE(done);
     132
    128133        fibril_mutex_lock(&instance->guard);
    129134        link_t *current = instance->batch_list.next;
     
    134139                if (batch_is_complete(batch)) {
    135140                        transfer_list_remove_batch(instance, batch);
    136                         batch->next_step(batch);
     141                        list_append(current, &done);
    137142                }
    138143                current = next;
    139144        }
    140145        fibril_mutex_unlock(&instance->guard);
     146
     147        while (!list_empty(&done)) {
     148                link_t *item = done.next;
     149                list_remove(item);
     150                batch_t *batch = list_get_instance(item, batch_t, link);
     151                batch->next_step(batch);
     152        }
    141153}
    142154/**
  • uspace/drv/uhci-hcd/transfer_list.h

    rdff940f8 r8c877b2  
    6060        queue_head_dispose(instance->queue_head);
    6161}
    62 void transfer_list_check(transfer_list_t *instance);
     62void transfer_list_remove_finished(transfer_list_t *instance);
    6363
    6464void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch);
  • uspace/drv/uhci-hcd/uhci-hcd.ma

    rdff940f8 r8c877b2  
    1110 pci/ven=8086&dev=7020
    2210 pci/ven=8086&dev=7112
     3
     410 pci/ven=8086&dev=27c8
     510 pci/ven=8086&dev=27c9
     610 pci/ven=8086&dev=27ca
     710 pci/ven=8086&dev=27cb
     8
     9
     1010 pci/ven=8086&dev=2830
     1110 pci/ven=8086&dev=2831
     1210 pci/ven=8086&dev=2832
     1310 pci/ven=8086&dev=2834
     1410 pci/ven=8086&dev=2835
     15
     1610 pci/ven=8086&dev=2934
     1710 pci/ven=8086&dev=2935
     1810 pci/ven=8086&dev=2936
     1910 pci/ven=8086&dev=2937
     2010 pci/ven=8086&dev=2938
     2110 pci/ven=8086&dev=2939
  • uspace/drv/uhci-hcd/uhci.c

    rdff940f8 r8c877b2  
    4848        {
    4949                .cmd = CMD_PIO_READ_16,
    50                 .addr = (void*)0xc022,
     50                .addr = NULL, /* patched for every instance */
    5151                .dstarg = 1
    5252        },
    5353        {
    5454                .cmd = CMD_PIO_WRITE_16,
    55                 .addr = (void*)0xc022,
     55                .addr = NULL, /* pathed for every instance */
    5656                .value = 0x1f
    5757        },
     
    6868        assert(hc);
    6969
    70         usb_address_t addr = usb_address_keeping_find(&hc->address_manager,
     70        usb_address_t addr = device_keeper_find(&hc->device_manager,
    7171            handle);
    7272        if (addr < 0) {
     
    8080        return EOK;
    8181}
    82 
    83 
     82/*----------------------------------------------------------------------------*/
    8483static usb_iface_t hc_usb_iface = {
    8584        .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
     
    8988static ddf_dev_ops_t uhci_ops = {
    9089        .interfaces[USB_DEV_IFACE] = &hc_usb_iface,
    91         .interfaces[USBHC_DEV_IFACE] = &uhci_iface
     90        .interfaces[USBHC_DEV_IFACE] = &uhci_iface,
    9291};
    93 
     92/*----------------------------------------------------------------------------*/
    9493static int uhci_init_transfer_lists(uhci_t *instance);
    9594static int uhci_init_mem_structures(uhci_t *instance);
     
    102101        bool low_speed, usb_transfer_type_t, size_t size);
    103102
    104 #define CHECK_RET_RETURN(ret, message...) \
     103
     104int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size)
     105{
     106        assert(reg_size >= sizeof(regs_t));
     107        int ret;
     108
     109#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
    105110        if (ret != EOK) { \
    106111                usb_log_error(message); \
     112                if (instance->ddf_instance) \
     113                        ddf_fun_destroy(instance->ddf_instance); \
    107114                return ret; \
    108115        } else (void) 0
    109116
    110 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size)
    111 {
    112         assert(reg_size >= sizeof(regs_t));
    113         int ret;
    114 
    115         /*
    116          * Create UHCI function.
    117          */
     117        /* Create UHCI function. */
    118118        instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci");
    119         if (instance->ddf_instance == NULL) {
    120                 usb_log_error("Failed to create UHCI device function.\n");
    121                 return ENOMEM;
    122         }
     119        ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK;
     120        CHECK_RET_DEST_FUN_RETURN(ret,
     121            "Failed to create UHCI device function.\n");
     122
    123123        instance->ddf_instance->ops = &uhci_ops;
    124124        instance->ddf_instance->driver_data = instance;
    125125
    126126        ret = ddf_fun_bind(instance->ddf_instance);
    127         CHECK_RET_RETURN(ret, "Failed to bind UHCI device function: %s.\n",
    128             str_error(ret));
     127        CHECK_RET_DEST_FUN_RETURN(ret,
     128            "Failed(%d) to bind UHCI device function: %s.\n",
     129            ret, str_error(ret));
    129130
    130131        /* allow access to hc control registers */
    131132        regs_t *io;
    132133        ret = pio_enable(regs, reg_size, (void**)&io);
    133         CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p.\n", io);
     134        CHECK_RET_DEST_FUN_RETURN(ret,
     135            "Failed(%d) to gain access to registers at %p: %s.\n",
     136            ret, str_error(ret), io);
    134137        instance->registers = io;
    135         usb_log_debug("Device registers accessible.\n");
     138        usb_log_debug("Device registers at %p(%u) accessible.\n",
     139            io, reg_size);
    136140
    137141        ret = uhci_init_mem_structures(instance);
    138         CHECK_RET_RETURN(ret, "Failed to initialize memory structures.\n");
     142        CHECK_RET_DEST_FUN_RETURN(ret,
     143            "Failed to initialize UHCI memory structures.\n");
    139144
    140145        uhci_init_hw(instance);
    141 
    142         instance->cleaner = fibril_create(uhci_interrupt_emulator, instance);
    143 //      fibril_add_ready(instance->cleaner);
     146        instance->cleaner =
     147            fibril_create(uhci_interrupt_emulator, instance);
     148        fibril_add_ready(instance->cleaner);
    144149
    145150        instance->debug_checker = fibril_create(uhci_debug_checker, instance);
    146151        fibril_add_ready(instance->debug_checker);
    147152
    148         return EOK;
     153        usb_log_info("Started UHCI driver.\n");
     154        return EOK;
     155#undef CHECK_RET_DEST_FUN_RETURN
    149156}
    150157/*----------------------------------------------------------------------------*/
    151158void uhci_init_hw(uhci_t *instance)
    152159{
     160        assert(instance);
     161
     162        /* reset everything, who knows what touched it before us */
     163        pio_write_16(&instance->registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
     164        async_usleep(10000); /* 10ms according to USB spec */
     165        pio_write_16(&instance->registers->usbcmd, 0);
     166
     167        /* reset hc, all states and counters */
     168        pio_write_16(&instance->registers->usbcmd, UHCI_CMD_HCRESET);
     169        while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0)
     170                { async_usleep(10); }
    153171
    154172        /* set framelist pointer */
     
    158176        /* enable all interrupts, but resume interrupt */
    159177        pio_write_16(&instance->registers->usbintr,
    160                   UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
     178            UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
    161179
    162180        /* Start the hc with large(64B) packet FSBR */
    163181        pio_write_16(&instance->registers->usbcmd,
    164182            UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
    165         usb_log_debug("Started UHCI HC.\n");
    166183}
    167184/*----------------------------------------------------------------------------*/
     
    169186{
    170187        assert(instance);
     188#define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \
     189        if (ret != EOK) { \
     190                usb_log_error(message); \
     191                if (instance->interrupt_code.cmds != NULL) \
     192                        free(instance->interrupt_code.cmds); \
     193                return ret; \
     194        } else (void) 0
    171195
    172196        /* init interrupt code */
    173         irq_cmd_t *interrupt_commands = malloc(sizeof(uhci_cmds));
    174         if (interrupt_commands == NULL) {
    175                 return ENOMEM;
    176         }
    177         memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
    178         interrupt_commands[0].addr = (void*)&instance->registers->usbsts;
    179         interrupt_commands[1].addr = (void*)&instance->registers->usbsts;
    180         instance->interrupt_code.cmds = interrupt_commands;
    181         instance->interrupt_code.cmdcount =
    182             sizeof(uhci_cmds) / sizeof(irq_cmd_t);
     197        instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds));
     198        int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK;
     199        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to allocate interrupt cmds space.\n");
     200
     201        {
     202                irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds;
     203                memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
     204                interrupt_commands[0].addr = (void*)&instance->registers->usbsts;
     205                interrupt_commands[1].addr = (void*)&instance->registers->usbsts;
     206                instance->interrupt_code.cmdcount =
     207                    sizeof(uhci_cmds) / sizeof(irq_cmd_t);
     208        }
    183209
    184210        /* init transfer lists */
    185         int ret = uhci_init_transfer_lists(instance);
    186         CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
     211        ret = uhci_init_transfer_lists(instance);
     212        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to initialize transfer lists.\n");
    187213        usb_log_debug("Initialized transfer lists.\n");
    188214
     
    190216        instance->frame_list = get_page();
    191217        ret = instance ? EOK : ENOMEM;
    192         CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
     218        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n");
    193219        usb_log_debug("Initialized frame list.\n");
    194220
     
    197223          instance->transfers_interrupt.queue_head_pa
    198224          | LINK_POINTER_QUEUE_HEAD_FLAG;
     225
    199226        unsigned i = 0;
    200227        for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
     
    203230
    204231        /* init address keeper(libusb) */
    205         usb_address_keeping_init(&instance->address_manager, USB11_ADDRESS_MAX);
    206         usb_log_debug("Initialized address manager.\n");
    207 
    208         return EOK;
     232        device_keeper_init(&instance->device_manager);
     233        usb_log_debug("Initialized device manager.\n");
     234
     235        return EOK;
     236#undef CHECK_RET_DEST_CMDS_RETURN
    209237}
    210238/*----------------------------------------------------------------------------*/
     
    212240{
    213241        assert(instance);
     242#define CHECK_RET_CLEAR_RETURN(ret, message...) \
     243        if (ret != EOK) { \
     244                usb_log_error(message); \
     245                transfer_list_fini(&instance->transfers_bulk_full); \
     246                transfer_list_fini(&instance->transfers_control_full); \
     247                transfer_list_fini(&instance->transfers_control_slow); \
     248                transfer_list_fini(&instance->transfers_interrupt); \
     249                return ret; \
     250        } else (void) 0
    214251
    215252        /* initialize TODO: check errors */
    216253        int ret;
    217254        ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
    218         assert(ret == EOK);
     255        CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
     256
    219257        ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL");
    220         assert(ret == EOK);
     258        CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
     259
    221260        ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW");
    222         assert(ret == EOK);
     261        CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
     262
    223263        ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
    224         assert(ret == EOK);
     264        CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list.");
    225265
    226266        transfer_list_set_next(&instance->transfers_control_full,
     
    249289
    250290        return EOK;
     291#undef CHECK_RET_CLEAR_RETURN
    251292}
    252293/*----------------------------------------------------------------------------*/
     
    255296        assert(instance);
    256297        assert(batch);
    257         const int low_speed = (batch->speed == LOW_SPEED);
     298        const int low_speed = (batch->speed == USB_SPEED_LOW);
    258299        if (!allowed_usb_packet(
    259300            low_speed, batch->transfer_type, batch->max_packet_size)) {
    260301                usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n",
    261                           low_speed ? "LOW" : "FULL" , batch->transfer_type,
     302                    low_speed ? "LOW" : "FULL" , batch->transfer_type,
    262303                    batch->max_packet_size);
    263304                return ENOTSUP;
     
    276317{
    277318        assert(instance);
    278         if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0)
    279                 return;
    280         usb_log_debug("UHCI interrupt: %X.\n", status);
    281         transfer_list_check(&instance->transfers_interrupt);
    282         transfer_list_check(&instance->transfers_control_slow);
    283         transfer_list_check(&instance->transfers_control_full);
    284         transfer_list_check(&instance->transfers_bulk_full);
     319        transfer_list_remove_finished(&instance->transfers_interrupt);
     320        transfer_list_remove_finished(&instance->transfers_control_slow);
     321        transfer_list_remove_finished(&instance->transfers_control_full);
     322        transfer_list_remove_finished(&instance->transfers_bulk_full);
    285323}
    286324/*----------------------------------------------------------------------------*/
     
    291329        assert(instance);
    292330
    293         while(1) {
     331        while (1) {
    294332                uint16_t status = pio_read_16(&instance->registers->usbsts);
     333                if (status != 0)
     334                        usb_log_debug2("UHCI status: %x.\n", status);
     335                status |= 1;
    295336                uhci_interrupt(instance, status);
    296                 async_usleep(UHCI_CLEANER_TIMEOUT);
     337                pio_write_16(&instance->registers->usbsts, 0x1f);
     338                async_usleep(UHCI_CLEANER_TIMEOUT * 5);
    297339        }
    298340        return EOK;
     
    303345        uhci_t *instance = (uhci_t*)arg;
    304346        assert(instance);
     347
     348#define QH(queue) \
     349        instance->transfers_##queue.queue_head
     350
    305351        while (1) {
    306352                const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
    307353                const uint16_t sts = pio_read_16(&instance->registers->usbsts);
    308                 const uint16_t intr = pio_read_16(&instance->registers->usbintr);
    309                 usb_log_debug("Command: %X Status: %X Interrupts: %x\n",
    310                     cmd, sts, intr);
    311 
    312                 uintptr_t frame_list = pio_read_32(&instance->registers->flbaseadd);
     354                const uint16_t intr =
     355                    pio_read_16(&instance->registers->usbintr);
     356
     357                if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
     358                        usb_log_debug2("Command: %X Status: %X Intr: %x\n",
     359                            cmd, sts, intr);
     360                }
     361
     362                uintptr_t frame_list =
     363                    pio_read_32(&instance->registers->flbaseadd) & ~0xfff;
    313364                if (frame_list != addr_to_phys(instance->frame_list)) {
    314365                        usb_log_debug("Framelist address: %p vs. %p.\n",
    315                                 frame_list, addr_to_phys(instance->frame_list));
    316                 }
     366                            frame_list, addr_to_phys(instance->frame_list));
     367                }
     368
    317369                int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
    318370                usb_log_debug2("Framelist item: %d \n", frnum );
    319371
    320                 queue_head_t* qh = instance->transfers_interrupt.queue_head;
    321 
    322                 if ((instance->frame_list[frnum] & (~0xf)) != (uintptr_t)addr_to_phys(qh)) {
     372                uintptr_t expected_pa = instance->frame_list[frnum] & (~0xf);
     373                uintptr_t real_pa = addr_to_phys(QH(interrupt));
     374                if (expected_pa != real_pa) {
    323375                        usb_log_debug("Interrupt QH: %p vs. %p.\n",
    324                                 instance->frame_list[frnum] & (~0xf), addr_to_phys(qh));
    325                 }
    326 
    327                 if ((qh->next_queue & (~0xf))
    328                   != (uintptr_t)addr_to_phys(instance->transfers_control_slow.queue_head)) {
    329                         usb_log_debug("Control Slow QH: %p vs. %p.\n", qh->next_queue & (~0xf),
    330                                 addr_to_phys(instance->transfers_control_slow.queue_head));
    331                 }
    332                 qh = instance->transfers_control_slow.queue_head;
    333 
    334                 if ((qh->next_queue & (~0xf))
    335                   != (uintptr_t)addr_to_phys(instance->transfers_control_full.queue_head)) {
    336                         usb_log_debug("Control Full QH: %p vs. %p.\n", qh->next_queue & (~0xf),
    337                                 addr_to_phys(instance->transfers_control_full.queue_head));\
    338                 }
    339                 qh = instance->transfers_control_full.queue_head;
    340 
    341                 if ((qh->next_queue & (~0xf))
    342                   != (uintptr_t)addr_to_phys(instance->transfers_bulk_full.queue_head)) {
    343                         usb_log_debug("Bulk QH: %p vs. %p.\n", qh->next_queue & (~0xf),
    344                                 addr_to_phys(instance->transfers_bulk_full.queue_head));
    345                 }
    346 /*
    347         uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
    348         cmd |= UHCI_CMD_RUN_STOP;
    349         pio_write_16(&instance->registers->usbcmd, cmd);
    350 */
     376                            expected_pa, real_pa);
     377                }
     378
     379                expected_pa = QH(interrupt)->next_queue & (~0xf);
     380                real_pa = addr_to_phys(QH(control_slow));
     381                if (expected_pa != real_pa) {
     382                        usb_log_debug("Control Slow QH: %p vs. %p.\n",
     383                            expected_pa, real_pa);
     384                }
     385
     386                expected_pa = QH(control_slow)->next_queue & (~0xf);
     387                real_pa = addr_to_phys(QH(control_full));
     388                if (expected_pa != real_pa) {
     389                        usb_log_debug("Control Full QH: %p vs. %p.\n",
     390                            expected_pa, real_pa);
     391                }
     392
     393                expected_pa = QH(control_full)->next_queue & (~0xf);
     394                real_pa = addr_to_phys(QH(bulk_full));
     395                if (expected_pa != real_pa ) {
     396                        usb_log_debug("Bulk QH: %p vs. %p.\n",
     397                            expected_pa, real_pa);
     398                }
    351399                async_usleep(UHCI_DEBUGER_TIMEOUT);
    352400        }
    353401        return 0;
     402#undef QH
    354403}
    355404/*----------------------------------------------------------------------------*/
    356405bool allowed_usb_packet(
    357         bool low_speed, usb_transfer_type_t transfer, size_t size)
     406    bool low_speed, usb_transfer_type_t transfer, size_t size)
    358407{
    359408        /* see USB specification chapter 5.5-5.8 for magic numbers used here */
    360         switch(transfer) {
    361                 case USB_TRANSFER_ISOCHRONOUS:
    362                         return (!low_speed && size < 1024);
    363                 case USB_TRANSFER_INTERRUPT:
    364                         return size <= (low_speed ? 8 : 64);
    365                 case USB_TRANSFER_CONTROL: /* device specifies its own max size */
    366                         return (size <= (low_speed ? 8 : 64));
    367                 case USB_TRANSFER_BULK: /* device specifies its own max size */
    368                         return (!low_speed && size <= 64);
     409        switch(transfer)
     410        {
     411        case USB_TRANSFER_ISOCHRONOUS:
     412                return (!low_speed && size < 1024);
     413        case USB_TRANSFER_INTERRUPT:
     414                return size <= (low_speed ? 8 : 64);
     415        case USB_TRANSFER_CONTROL: /* device specifies its own max size */
     416                return (size <= (low_speed ? 8 : 64));
     417        case USB_TRANSFER_BULK: /* device specifies its own max size */
     418                return (!low_speed && size <= 64);
    369419        }
    370420        return false;
  • uspace/drv/uhci-hcd/uhci.h

    rdff940f8 r8c877b2  
    4141#include <ddi.h>
    4242
    43 #include <usb/addrkeep.h>
    4443#include <usbhc_iface.h>
    4544
     45#include "batch.h"
    4646#include "transfer_list.h"
    47 #include "batch.h"
     47#include "utils/device_keeper.h"
    4848
    4949typedef struct uhci_regs {
     
    8282
    8383typedef struct uhci {
    84         usb_address_keeping_t address_manager;
     84        device_keeper_t device_manager;
     85
    8586        volatile regs_t *registers;
    8687
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c

    rdff940f8 r8c877b2  
    3939
    4040void transfer_descriptor_init(transfer_descriptor_t *instance,
    41     int error_count, size_t size, bool toggle, bool isochronous,
     41    int error_count, size_t size, bool toggle, bool isochronous, bool low_speed,
    4242    usb_target_t target, int pid, void *buffer, transfer_descriptor_t *next)
    4343{
     
    5050        instance->status = 0
    5151          | ((error_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
     52                | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
    5253          | TD_STATUS_ERROR_ACTIVE;
    5354
     
    6667        }
    6768
    68         usb_log_info("Created TD: %X:%X:%X:%X(%p).\n",
     69        usb_log_debug2("Created TD: %X:%X:%X:%X(%p).\n",
    6970                instance->next, instance->status, instance->device,
    7071          instance->buffer_ptr, buffer);
    71 #if 0
    72         if (size) {
    73                 unsigned char * buff = buffer;
    74                 uhci_print_verbose("TD Buffer dump(%p-%dB): ", buffer, size);
    75                 unsigned i = 0;
    76                 /* TODO: Verbose? */
    77                 for (; i < size; ++i) {
    78                         printf((i & 1) ? "%x " : "%x", buff[i]);
    79                 }
    80                 printf("\n");
    81         }
    82 #endif
    8372}
    8473/*----------------------------------------------------------------------------*/
     
    8877
    8978        if ((instance->status & TD_STATUS_ERROR_STALLED) != 0)
    90                 return EIO;
     79                return ESTALL;
    9180
    9281        if ((instance->status & TD_STATUS_ERROR_CRC) != 0)
    93                 return EAGAIN;
     82                return EBADCHECKSUM;
    9483
    9584        if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0)
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h

    rdff940f8 r8c877b2  
    9292
    9393void transfer_descriptor_init(transfer_descriptor_t *instance,
    94     int error_count, size_t size, bool toggle, bool isochronous,
     94    int error_count, size_t size, bool toggle, bool isochronous, bool low_speed,
    9595    usb_target_t target, int pid, void *buffer, transfer_descriptor_t * next);
    9696
Note: See TracChangeset for help on using the changeset viewer.