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

Changeset f58154c5 in mainline


Ignore:
Timestamp:
2011-05-18T10:59:50Z (11 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master
Children:
17fc40c
Parents:
b2995c3 (diff), aeca5a3 (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:

Minor fixes and comments

UHCI: use provided barrier defines (buffer allocator should be able to use cacheable memory)
libusb: make usb enumeration routine follow USB spec more closely (wait periods)
OHCI: handle hw errors
OHCI: use provided barrier defines (buffer allocator should be able to use cacheable memory)
OHCI: reduce maximum buffer size for one transaction, this relaxes requirements on allocator providing hw accessible buffers.(memory does not have to be continuous) The only requirement that stays is the 32bit pointers limit.

Files:
14 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

    rb2995c3 rf58154c5  
    5353./uspace/app/klog/klog
    5454./uspace/app/lsusb/lsusb
     55./uspace/app/mkbd/mkbd
    5556./uspace/app/mkfat/mkfat
    5657./uspace/app/netstart/netstart
  • uspace/drv/ohci/batch.c

    rb2995c3 rf58154c5  
    4444#include "hw_struct/transfer_descriptor.h"
    4545
     46/** OHCI specific data required for USB transfer */
    4647typedef struct ohci_transfer_batch {
     48        /** Endpoint descriptor of the target endpoint. */
    4749        ed_t *ed;
     50        /** List of TDs needed for the transfer */
    4851        td_t **tds;
     52        /** Number of TDs used by the transfer */
    4953        size_t td_count;
     54        /** Dummy TD to be left at the ED and used by the next transfer */
    5055        size_t leave_td;
    51         char *device_buffer;
     56        /** Data buffer, must be accessible byb the OHCI hw. */
     57        void *device_buffer;
    5258} ohci_transfer_batch_t;
    53 
     59/*----------------------------------------------------------------------------*/
     60static void batch_control(usb_transfer_batch_t *instance,
     61    usb_direction_t data_dir, usb_direction_t status_dir);
     62static void batch_data(usb_transfer_batch_t *instance);
     63/*----------------------------------------------------------------------------*/
     64/** Safely destructs ohci_transfer_batch_t structure
     65 *
     66 * @param[in] ohci_batch Instance to destroy.
     67 */
    5468static void ohci_transfer_batch_dispose(void *ohci_batch)
    5569{
     
    6983}
    7084/*----------------------------------------------------------------------------*/
    71 static void batch_control(usb_transfer_batch_t *instance,
    72     usb_direction_t data_dir, usb_direction_t status_dir);
    73 static void batch_data(usb_transfer_batch_t *instance);
    74 /*----------------------------------------------------------------------------*/
     85/** Allocate memory initialize internal structures
     86 *
     87 * @param[in] fun DDF function to pass to callback.
     88 * @param[in] ep Communication target
     89 * @param[in] buffer Data source/destination.
     90 * @param[in] buffer_size Size of the buffer.
     91 * @param[in] setup_buffer Setup data source (if not NULL)
     92 * @param[in] setup_size Size of setup_buffer (should be always 8)
     93 * @param[in] func_in function to call on inbound transfer completion
     94 * @param[in] func_out function to call on outbound transfer completion
     95 * @param[in] arg additional parameter to func_in or func_out
     96 * @return Valid pointer if all structures were successfully created,
     97 * NULL otherwise.
     98 *
     99 * Allocates and initializes structures needed by the OHCI hw for the transfer.
     100 */
    75101usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
    76102    char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
     
    107133        }
    108134
    109         /* we need one extra place for td that is currently assigned to hcd_ep*/
     135        /* We need an extra place for TD that is currently assigned to hcd_ep*/
    110136        data->tds = calloc(sizeof(td_t*), data->td_count + 1);
    111137        CHECK_NULL_DISPOSE_RETURN(data->tds,
    112138            "Failed to allocate transfer descriptors.\n");
    113139
     140        /* Add TD left over by the previous transfer */
    114141        data->tds[0] = hcd_ep->td;
    115142        data->leave_td = 0;
     
    123150        data->ed = hcd_ep->ed;
    124151
     152        /* NOTE: OHCI is capable of handling buffer that crosses page boundaries
     153         * it is, however, not capable of handling buffer that occupies more
     154         * than two pages (the first page is computed using start pointer, the
     155         * other using the end pointer) */
    125156        if (setup_size + buffer_size > 0) {
    126157                data->device_buffer = malloc32(setup_size + buffer_size);
     
    135166}
    136167/*----------------------------------------------------------------------------*/
     168/** Check batch TDs' status.
     169 *
     170 * @param[in] instance Batch structure to use.
     171 * @return False, if there is an active TD, true otherwise.
     172 *
     173 * Walk all TDs (usually there is just one). Stop with false if there is an
     174 * active TD. Stop with true if an error is found. Return true if the walk
     175 * completes with the last TD.
     176 */
    137177bool batch_is_complete(usb_transfer_batch_t *instance)
    138178{
     
    140180        ohci_transfer_batch_t *data = instance->private_data;
    141181        assert(data);
    142         size_t tds = data->td_count;
    143182        usb_log_debug("Batch(%p) checking %zu td(s) for completion.\n",
    144             instance, tds);
     183            instance, data->td_count);
    145184        usb_log_debug("ED: %x:%x:%x:%x.\n",
    146185            data->ed->status, data->ed->td_head, data->ed->td_tail,
     
    148187        size_t i = 0;
    149188        instance->transfered_size = instance->buffer_size;
    150         for (; i < tds; ++i) {
     189        for (; i < data->td_count; ++i) {
    151190                assert(data->tds[i] != NULL);
    152191                usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i,
     
    173212        assert(hcd_ep);
    174213        hcd_ep->td = data->tds[i];
    175         if (i > 0)
    176                 instance->transfered_size -= td_remain_size(data->tds[i - 1]);
     214        assert(i > 0);
     215        for (--i;i < data->td_count; ++i)
     216                instance->transfered_size -= td_remain_size(data->tds[i]);
    177217
    178218        /* Clear possible ED HALT */
    179219        data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
    180         uint32_t pa = addr_to_phys(hcd_ep->td);
     220        const uint32_t pa = addr_to_phys(hcd_ep->td);
    181221        assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK));
    182222        assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK));
     
    185225}
    186226/*----------------------------------------------------------------------------*/
     227/** Starts execution of the TD list
     228 *
     229 * @param[in] instance Batch structure to use
     230 */
    187231void batch_commit(usb_transfer_batch_t *instance)
    188232{
     
    193237}
    194238/*----------------------------------------------------------------------------*/
     239/** Prepares control write transfer.
     240 *
     241 * @param[in] instance Batch structure to use.
     242 *
     243 * Uses generic control transfer using direction OUT(data stage) and
     244 * IN(status stage).
     245 */
    195246void batch_control_write(usb_transfer_batch_t *instance)
    196247{
     
    203254}
    204255/*----------------------------------------------------------------------------*/
     256/** Prepares control read transfer.
     257 *
     258 * @param[in] instance Batch structure to use.
     259 *
     260 * Uses generic control transfer using direction IN(data stage) and
     261 * OUT(status stage).
     262 */
    205263void batch_control_read(usb_transfer_batch_t *instance)
    206264{
     
    211269}
    212270/*----------------------------------------------------------------------------*/
     271/** Prepare interrupt in transfer.
     272 *
     273 * @param[in] instance Batch structure to use.
     274 *
     275 * Data transfer.
     276 */
    213277void batch_interrupt_in(usb_transfer_batch_t *instance)
    214278{
     
    219283}
    220284/*----------------------------------------------------------------------------*/
     285/** Prepare interrupt out transfer.
     286 *
     287 * @param[in] instance Batch structure to use.
     288 *
     289 * Data transfer.
     290 */
    221291void batch_interrupt_out(usb_transfer_batch_t *instance)
    222292{
     
    229299}
    230300/*----------------------------------------------------------------------------*/
     301/** Prepare bulk in transfer.
     302 *
     303 * @param[in] instance Batch structure to use.
     304 *
     305 * Data transfer.
     306 */
    231307void batch_bulk_in(usb_transfer_batch_t *instance)
    232308{
     
    237313}
    238314/*----------------------------------------------------------------------------*/
     315/** Prepare bulk out transfer.
     316 *
     317 * @param[in] instance Batch structure to use.
     318 *
     319 * Data transfer.
     320 */
    239321void batch_bulk_out(usb_transfer_batch_t *instance)
    240322{
     
    247329}
    248330/*----------------------------------------------------------------------------*/
    249 ed_t * batch_ed(usb_transfer_batch_t *instance)
    250 {
    251         assert(instance);
    252         ohci_transfer_batch_t *data = instance->private_data;
    253         assert(data);
    254         return data->ed;
    255 }
    256 /*----------------------------------------------------------------------------*/
     331/** Prepare generic control transfer
     332 *
     333 * @param[in] instance Batch structure to use.
     334 * @param[in] data_dir Direction to use for data stage.
     335 * @param[in] status_dir Direction to use for status stage.
     336 *
     337 * Setup stage with toggle 0 and direction BOTH(SETUP_PID)
     338 * Data stage with alternating toggle and direction supplied by parameter.
     339 * Status stage with toggle 1 and direction supplied by parameter.
     340 */
    257341void batch_control(usb_transfer_batch_t *instance,
    258342    usb_direction_t data_dir, usb_direction_t status_dir)
     
    303387}
    304388/*----------------------------------------------------------------------------*/
     389/** Prepare generic data transfer
     390 *
     391 * @param[in] instance Batch structure to use.
     392 *
     393 * Direction is supplied by the associated ep and toggle is maintained by the
     394 * OHCI hw in ED.
     395 */
    305396void batch_data(usb_transfer_batch_t *instance)
    306397{
  • uspace/drv/ohci/batch.h

    rb2995c3 rf58154c5  
    4141#include <usb/host/batch.h>
    4242
    43 #include "hw_struct/endpoint_descriptor.h"
    44 
    4543usb_transfer_batch_t * batch_get(
    4644    ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
     
    6563
    6664void batch_bulk_out(usb_transfer_batch_t *instance);
    67 
    68 ed_t * batch_ed(usb_transfer_batch_t *instance);
    6965#endif
    7066/**
  • uspace/drv/ohci/endpoint_list.c

    rb2995c3 rf58154c5  
    3434#include <errno.h>
    3535#include <usb/debug.h>
     36#include <arch/barrier.h>
    3637
    3738#include "endpoint_list.h"
     
    4344 * @return Error code
    4445 *
    45  * Allocates memory for internal qh_t structure.
     46 * Allocates memory for internal ed_t structure.
    4647 */
    4748int endpoint_list_init(endpoint_list_t *instance, const char *name)
     
    6869 * @param[in] instance List to lead.
    6970 * @param[in] next List to append.
    70  * @return Error code
    7171 *
    72  * Does not check whether this replaces an existing list .
     72 * Does not check whether this replaces an existing list.
    7373 */
    7474void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
     
    7979}
    8080/*----------------------------------------------------------------------------*/
    81 /** Submit transfer endpoint to the list and queue.
     81/** Add endpoint to the list and queue.
    8282 *
    8383 * @param[in] instance List to use.
    84  * @param[in] endpoint Transfer endpoint to submit.
    85  * @return Error code
     84 * @param[in] endpoint Endpoint to add.
    8685 *
    8786 * The endpoint is added to the end of the list and queue.
     
    9998        /* Add to the hardware queue. */
    10099        if (list_empty(&instance->endpoint_list)) {
    101                 /* There is nothing scheduled */
     100                /* There are no active EDs */
    102101                last_ed = instance->list_head;
    103102        } else {
    104                 /* There is something scheduled */
     103                /* There are active EDs, get the last one */
    105104                hcd_endpoint_t *last = list_get_instance(
    106105                    instance->endpoint_list.prev, hcd_endpoint_t, link);
     106                assert(last);
    107107                last_ed = last->ed;
    108108        }
    109         /* keep link */
     109        /* Keep link */
    110110        hcd_ep->ed->next = last_ed->next;
     111        /* Make sure ED is written to the memory */
     112        write_barrier();
     113
     114        /* Add ed to the hw queue */
    111115        ed_append_ed(last_ed, hcd_ep->ed);
     116        /* Make sure ED is updated */
     117        write_barrier();
    112118
    113         asm volatile ("": : :"memory");
    114 
    115         /* Add to the driver list */
     119        /* Add to the sw list */
    116120        list_append(&hcd_ep->link, &instance->endpoint_list);
    117121
     
    129133}
    130134/*----------------------------------------------------------------------------*/
    131 #if 0
    132 /** Create list for finished endpoints.
     135/** Remove endpoint from the list and queue.
    133136 *
    134137 * @param[in] instance List to use.
    135  * @param[in] done list to fill
    136  */
    137 void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done)
    138 {
    139         assert(instance);
    140         assert(done);
    141 
    142         fibril_mutex_lock(&instance->guard);
    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) {
    147                 link_t *next = current->next;
    148                 hcd_endpoint_t *endpoint =
    149                     list_get_instance(current, hcd_endpoint_t, link);
    150 
    151                 if (endpoint_is_complete(endpoint)) {
    152                         /* Save for post-processing */
    153                         endpoint_list_remove_endpoint(instance, endpoint);
    154                         list_append(current, done);
    155                 }
    156                 current = next;
    157         }
    158         fibril_mutex_unlock(&instance->guard);
    159 }
    160 /*----------------------------------------------------------------------------*/
    161 /** Walk the list and abort all endpointes.
    162  *
    163  * @param[in] instance List to use.
    164  */
    165 void 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.
    183  * @return Error code
    184  *
    185  * Does not lock the transfer list, caller is responsible for that.
     138 * @param[in] endpoint Endpoint to remove.
    186139 */
    187140void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
     
    212165        assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed));
    213166        prev_ed->next = hcd_ep->ed->next;
     167        /* Make sure ED is updated */
     168        write_barrier();
    214169
    215         asm volatile ("": : :"memory");
    216170        usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n",
    217171            hcd_ep, qpos, instance->name, hcd_ep->ed->next);
  • uspace/drv/ohci/endpoint_list.h

    rb2995c3 rf58154c5  
    4141#include "utils/malloc32.h"
    4242
    43 typedef struct endpoint_list {
     43/** Structure maintains both OHCI queue and software list of active endpoints.*/
     44typedef struct endpoint_list
     45{
     46        /** Guard against add/remove races */
    4447        fibril_mutex_t guard;
     48        /** OHCI hw structure at the beginning of the queue */
    4549        ed_t *list_head;
     50        /** Physical address of the first(dummy) ED */
    4651        uint32_t list_head_pa;
     52        /** Assigned name, provides nicer debug output */
    4753        const char *name;
     54        /** Sw list of all active EDs */
    4855        link_t endpoint_list;
    4956} endpoint_list_t;
     
    5360 * @param[in] instance Memory place to use.
    5461 *
    55  * Frees memory for internal qh_t structure.
     62 * Frees memory of the internal ed_t structure.
    5663 */
    5764static inline void endpoint_list_fini(endpoint_list_t *instance)
     
    6875
    6976void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
    70 #if 0
    71 void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done);
    72 
    73 void endpoint_list_abort_all(endpoint_list_t *instance);
    74 #endif
    7577#endif
    7678/**
  • uspace/drv/ohci/hc.c

    rb2995c3 rf58154c5  
    293293                rh_interrupt(&instance->rh);
    294294
    295 
    296295        if (status & I_WDH) {
    297296                fibril_mutex_lock(&instance->guard);
     
    316315                fibril_mutex_unlock(&instance->guard);
    317316        }
     317
     318        if (status & I_UE) {
     319                hc_start_hw(instance);
     320        }
     321
    318322}
    319323/*----------------------------------------------------------------------------*/
     
    450454{
    451455        assert(instance);
    452 
    453456#define SETUP_ENDPOINT_LIST(type) \
    454457do { \
     
    458461                usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
    459462                    ret, name); \
    460                 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \
     463                endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\
    461464                endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
    462465                endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \
  • uspace/drv/ohci/hcd_endpoint.h

    rb2995c3 rf58154c5  
    3737#include <assert.h>
    3838#include <adt/list.h>
    39 
    4039#include <usb/host/endpoint.h>
    4140
     
    4342#include "hw_struct/transfer_descriptor.h"
    4443
    45 typedef struct hcd_endpoint {
     44typedef struct hcd_endpoint
     45{
    4646        ed_t *ed;
    4747        td_t *td;
  • uspace/drv/ohci/hw_struct/transfer_descriptor.c

    rb2995c3 rf58154c5  
    4444        assert(instance);
    4545        bzero(instance, sizeof(td_t));
    46         instance-> status = 0
     46        instance->status = 0
    4747            | ((dp[dir] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)
    4848            | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT);
  • uspace/drv/ohci/hw_struct/transfer_descriptor.h

    rb2995c3 rf58154c5  
    4141#include "completion_codes.h"
    4242
    43 /* OHCI TDs can handle up to 8KB buffers */
    44 #define OHCI_TD_MAX_TRANSFER (8 * 1024)
     43/* OHCI TDs can handle up to 8KB buffers, however, it can use max 2 pages.
     44 * Using 4KB buffers guarantees the page count condition.
     45 * (OHCI assumes 4KB pages) */
     46#define OHCI_TD_MAX_TRANSFER (4 * 1024)
    4547
    4648typedef struct td {
  • uspace/drv/uhci-hcd/batch.c

    rb2995c3 rf58154c5  
    4545#define DEFAULT_ERROR_COUNT 3
    4646
     47/** UHCI specific data required for USB transfer */
    4748typedef struct uhci_transfer_batch {
     49        /** Queue head
     50         * This QH is used to maintain UHCI schedule structure and the element
     51         * pointer points to the first TD of this batch.
     52         */
    4853        qh_t *qh;
     54        /** List of TDs needed for the transfer */
    4955        td_t *tds;
     56        /** Number of TDs used by the transfer */
     57        size_t td_count;
     58        /** Data buffer, must be accessible by the UHCI hw */
    5059        void *device_buffer;
    51         size_t td_count;
    5260} uhci_transfer_batch_t;
    5361/*----------------------------------------------------------------------------*/
    54 static void uhci_transfer_batch_dispose(void *uhci_batch)
    55 {
    56         uhci_transfer_batch_t *instance = uhci_batch;
    57         assert(instance);
    58         free32(instance->device_buffer);
    59         free(instance);
    60 }
    61 /*----------------------------------------------------------------------------*/
    62 
    6362static void batch_control(usb_transfer_batch_t *instance,
    6463    usb_packet_id data_stage, usb_packet_id status_stage);
    6564static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
    66 
     65/*----------------------------------------------------------------------------*/
     66/** Safely destructs uhci_transfer_batch_t structure
     67 *
     68 * @param[in] uhci_batch Instance to destroy.
     69 */
     70static void uhci_transfer_batch_dispose(void *uhci_batch)
     71{
     72        uhci_transfer_batch_t *instance = uhci_batch;
     73        assert(instance);
     74        free32(instance->device_buffer);
     75        free(instance);
     76}
     77/*----------------------------------------------------------------------------*/
    6778/** Allocate memory and initialize internal data structure.
    6879 *
     
    173184                instance->error = td_status(&data->tds[i]);
    174185                if (instance->error != EOK) {
    175                         usb_log_debug("Batch(%p) found error TD(%zu):%" PRIx32 ".\n",
    176                             instance, i, data->tds[i].status);
     186                        usb_log_debug("Batch(%p) found error TD(%zu):%"
     187                            PRIx32 ".\n", instance, i, data->tds[i].status);
    177188                        td_print_status(&data->tds[i]);
    178189
     
    397408/*----------------------------------------------------------------------------*/
    398409/** Provides access to QH data structure.
     410 *
    399411 * @param[in] instance Batch pointer to use.
    400412 * @return Pointer to the QH used by the batch.
  • uspace/drv/uhci-hcd/transfer_list.c

    rb2995c3 rf58154c5  
    3434#include <errno.h>
    3535#include <usb/debug.h>
     36#include <arch/barrier.h>
    3637
    3738#include "transfer_list.h"
     
    7172 * @param[in] instance Memory place to use.
    7273 *
    73  * Frees memory for internal qh_t structure.
     74 * Frees memory of the internal qh_t structure.
    7475 */
    7576void transfer_list_fini(transfer_list_t *instance)
     
    126127        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
    127128
     129        /* Make sure all data in the batch are written */
     130        write_barrier();
     131
    128132        /* keep link */
    129133        batch_qh(batch)->next = last_qh->next;
    130134        qh_set_next_qh(last_qh, batch_qh(batch));
    131135
    132         asm volatile ("": : :"memory");
     136        /* Make sure the pointer is updated */
     137        write_barrier();
    133138
    134139        /* Add to the driver list */
     
    222227            == addr_to_phys(batch_qh(batch)));
    223228        prev_qh->next = batch_qh(batch)->next;
    224         asm volatile ("": : :"memory");
     229
     230        /* Make sure the pointer is updated */
     231        write_barrier();
     232
    225233        /* Remove from the batch list */
    226234        list_remove(&batch->link);
  • uspace/drv/uhci-hcd/utils/malloc32.h

    rb2995c3 rf58154c5  
    7474        if (size <= SLAB_ELEMENT_SIZE)
    7575                return slab_malloc_g();
    76         assert(false);
     76        usb_log_warning("Requested %zu bytes, current allocator can't handle "
     77            "that amount, pray that the standard malloc will suffice.", size);
    7778        return memalign(UHCI_STRCUTURES_ALIGNMENT, size);
    7879}
  • uspace/drv/uhci-rhd/port.c

    rb2995c3 rf58154c5  
    227227                while (uhci_port_read_status(port) & STATUS_IN_RESET);
    228228        }
     229        /* PIO delay, should not be longer than 3ms as the device might
     230         * enter suspend state. */
    229231        udelay(10);
    230232        /* Enable the port. */
    231233        uhci_port_set_enabled(port, true);
    232 
    233         /* Reset recovery period,
    234          * devices do not have to respond during this period
    235          */
    236         async_usleep(10000);
    237234        return EOK;
    238235}
  • uspace/lib/usbdev/src/hub.c

    rb2995c3 rf58154c5  
    4141#include <assert.h>
    4242#include <usb/debug.h>
     43#include <time.h>
    4344
    4445/** How much time to wait between attempts to register endpoint 0:0.
     
    218219
    219220        int rc;
     221        struct timeval start_time;
     222
     223        rc = gettimeofday(&start_time, NULL);
     224        if (rc != EOK) {
     225                return rc;
     226        }
    220227
    221228        rc = usb_hc_connection_open(&hc_conn);
     
    264271                }
    265272        } while (rc != EOK);
     273        struct timeval end_time;
     274
     275        rc = gettimeofday(&end_time, NULL);
     276        if (rc != EOK) {
     277                goto leave_release_default_address;
     278        }
     279
     280        /* According to the USB spec part 9.1.2 host allows 100ms time for
     281         * the insertion process to complete. According to 7.1.7.1 this is the
     282         * time between attach detected and port reset. However, the setup done
     283         * above might use much of this time so we should only wait to fill
     284         * up the 100ms quota*/
     285        suseconds_t elapsed = tv_sub(&end_time, &start_time);
     286        if (elapsed < 100000) {
     287                async_usleep(100000 - elapsed);
     288        }
    266289
    267290        /*
     
    273296                goto leave_release_default_address;
    274297        }
     298        /* USB spec 7.1.7.1: The USB System Software guarantees a minimum of
     299         * 10ms for reset recovery. Device response to any bus transactions
     300         * addressed to the default device address during the reset recovery
     301         * time is undefined.
     302         */
     303        async_usleep(10000);
    275304
    276305        rc = usb_pipe_probe_default_control(&ctrl_pipe);
Note: See TracChangeset for help on using the changeset viewer.