Changeset 5d4193c in mainline


Ignore:
Timestamp:
2011-02-11T12:06:05Z (14 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
03197ffc, fe1776c2
Parents:
960ff451 (diff), f96aefc (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:

UHCI internals rework, add support for ew control transfer API

Location:
uspace/drv
Files:
1 added
1 deleted
10 edited
1 moved

Legend:

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

    r960ff451 r5d4193c  
    3333
    3434SOURCES = \
    35         callback.c \
    3635        iface.c \
    3736        main.c \
     
    4039        uhci.c \
    4140        uhci_struct/transfer_descriptor.c \
    42         pci.c
     41        pci.c \
     42        tracker.c
    4343
    4444include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/uhci-hcd/iface.c

    r960ff451 r5d4193c  
    106106    usbhc_iface_transfer_out_callback_t callback, void *arg)
    107107{
    108         assert(dev);
    109         uhci_t *hc = dev_to_uhci(dev);
    110         assert(hc);
    111         return uhci_transfer(hc, dev, target, USB_TRANSFER_INTERRUPT, 0, USB_PID_OUT,
    112                 false, data, size, callback, NULL, arg);
     108        size_t max_packet_size = 8;
     109        dev_speed_t speed = FULL_SPEED;
     110
     111        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_INTERRUPT,
     112            max_packet_size, speed, data, size, NULL, callback, arg);
     113        if (!tracker)
     114                return ENOMEM;
     115        tracker_interrupt_out(tracker);
     116        return EOK;
    113117}
    114118/*----------------------------------------------------------------------------*/
     
    117121    usbhc_iface_transfer_in_callback_t callback, void *arg)
    118122{
    119         assert(dev);
    120         uhci_t *hc = dev_to_uhci(dev);
    121         assert(hc);
    122         return uhci_transfer(hc, dev, target, USB_TRANSFER_INTERRUPT, 0, USB_PID_IN,
    123                 false, data, size, NULL, callback, arg);
     123        size_t max_packet_size = 4;
     124        dev_speed_t speed = FULL_SPEED;
     125
     126        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_INTERRUPT,
     127            max_packet_size, speed, data, size, callback, NULL, arg);
     128        if (!tracker)
     129                return ENOMEM;
     130        tracker_interrupt_in(tracker);
     131        return EOK;
     132}
     133/*----------------------------------------------------------------------------*/
     134static int control_write(device_t *dev, usb_target_t target,
     135    void *setup_data, size_t setup_size, void *data, size_t size,
     136    usbhc_iface_transfer_out_callback_t callback, void *arg)
     137{
     138        size_t max_packet_size = 8;
     139        dev_speed_t speed = FULL_SPEED;
     140
     141        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     142            max_packet_size, speed, data, size, NULL, callback, arg);
     143        if (!tracker)
     144                return ENOMEM;
     145        tracker_control_write(tracker, setup_data, setup_size);
     146        return EOK;
     147}
     148/*----------------------------------------------------------------------------*/
     149static int control_read(device_t *dev, usb_target_t target,
     150    void *setup_data, size_t setup_size, void *data, size_t size,
     151    usbhc_iface_transfer_in_callback_t callback, void *arg)
     152{
     153        size_t max_packet_size = 8;
     154        dev_speed_t speed = FULL_SPEED;
     155
     156        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     157            max_packet_size, speed, data, size, callback, NULL, arg);
     158        if (!tracker)
     159                return ENOMEM;
     160        tracker_control_read(tracker, setup_data, setup_size);
     161        return EOK;
    124162}
    125163/*----------------------------------------------------------------------------*/
     
    128166    usbhc_iface_transfer_out_callback_t callback, void *arg)
    129167{
    130         assert(dev);
    131         uhci_t *hc = dev_to_uhci(dev);
    132         assert(hc);
    133         return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_SETUP,
    134                 false, data, size, callback, NULL, arg);
     168        usb_log_warning("Using deprecated API control write setup.\n");
     169        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     170            8, FULL_SPEED, data, size, NULL, callback, arg);
     171        if (!tracker)
     172                return ENOMEM;
     173        tracker_control_setup_old(tracker);
     174        return EOK;
    135175}
    136176/*----------------------------------------------------------------------------*/
     
    139179    usbhc_iface_transfer_out_callback_t callback, void *arg)
    140180{
    141         assert(dev);
    142         uhci_t *hc = dev_to_uhci(dev);
    143         assert(hc);
    144         return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 1, USB_PID_OUT,
    145                 false, data, size, callback, NULL, arg);
     181        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     182            size, FULL_SPEED, data, size, NULL, callback, arg);
     183        if (!tracker)
     184                return ENOMEM;
     185        tracker_control_write_data_old(tracker);
     186        return EOK;
    146187}
    147188/*----------------------------------------------------------------------------*/
     
    149190    usbhc_iface_transfer_in_callback_t callback, void *arg)
    150191{
    151         assert(dev);
    152         uhci_t *hc = dev_to_uhci(dev);
    153         assert(hc);
    154         return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_IN,
    155                 false, NULL, 0, NULL, callback, arg);
     192        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     193            0, FULL_SPEED, NULL, 0, callback, NULL, arg);
     194        if (!tracker)
     195                return ENOMEM;
     196        tracker_control_write_status_old(tracker);
     197        return EOK;
    156198}
    157199/*----------------------------------------------------------------------------*/
     
    160202    usbhc_iface_transfer_out_callback_t callback, void *arg)
    161203{
    162         assert(dev);
    163         uhci_t *hc = dev_to_uhci(dev);
    164         assert(hc);
    165         return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_SETUP,
    166                 false, data, size, callback, NULL, arg);
     204        usb_log_warning("Using deprecated API control read setup.\n");
     205        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     206            8, FULL_SPEED, data, size, NULL, callback, arg);
     207        if (!tracker)
     208                return ENOMEM;
     209        tracker_control_setup_old(tracker);
     210        return EOK;
    167211}
    168212/*----------------------------------------------------------------------------*/
     
    171215    usbhc_iface_transfer_in_callback_t callback, void *arg)
    172216{
    173         assert(dev);
    174         uhci_t *hc = dev_to_uhci(dev);
    175         assert(hc);
    176         return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 1, USB_PID_IN,
    177                 false, data, size, NULL, callback, arg);
     217        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     218            size, FULL_SPEED, data, size, callback, NULL, arg);
     219        if (!tracker)
     220                return ENOMEM;
     221        tracker_control_read_data_old(tracker);
     222        return EOK;
    178223}
    179224/*----------------------------------------------------------------------------*/
     
    181226    usbhc_iface_transfer_out_callback_t callback, void *arg)
    182227{
    183         assert(dev);
    184         uhci_t *hc = dev_to_uhci(dev);
    185         assert(hc);
    186         return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_OUT,
    187                 false, NULL, 0, callback, NULL, arg);
    188 }
    189 
    190 
     228        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     229            0, FULL_SPEED, NULL, 0, NULL, callback, arg);
     230        if (!tracker)
     231                return ENOMEM;
     232        tracker_control_read_status_old(tracker);
     233        return EOK;
     234}
     235/*----------------------------------------------------------------------------*/
    191236usbhc_iface_t uhci_iface = {
    192237        .tell_address = get_address,
     
    200245        .interrupt_out = interrupt_out,
    201246        .interrupt_in = interrupt_in,
     247
     248        .control_read = control_read,
     249        .control_write = control_write,
    202250
    203251        .control_write_setup = control_write_setup,
  • uspace/drv/uhci-hcd/tracker.h

    r960ff451 r5d4193c  
    11/*
    2  * Copyright (c) 2010 Jan Vesely
     2 * Copyright (c) 2011 Jan Vesely
    33 * All rights reserved.
    44 *
     
    3232 * @brief UHCI driver
    3333 */
    34 #ifndef DRV_UHCI_CALLBACK_H
    35 #define DRV_UHCI_CALLBACK_H
     34#ifndef DRV_UHCI_TRACKER_H
     35#define DRV_UHCI_TRACKER_H
     36
     37#include <adt/list.h>
    3638
    3739#include <usbhc_iface.h>
    3840#include <usb/usb.h>
    3941
    40 #include "utils/malloc32.h"
     42#include "uhci_struct/transfer_descriptor.h"
    4143
    42 typedef struct callback
     44typedef enum {
     45        LOW_SPEED,
     46        FULL_SPEED,
     47} dev_speed_t;
     48
     49typedef struct tracker
    4350{
    44         usbhc_iface_transfer_in_callback_t callback_in;
    45         usbhc_iface_transfer_out_callback_t callback_out;
    46         void *old_buffer;
    47         void *new_buffer;
     51        link_t link;
     52        usb_target_t target;
     53        usb_transfer_type_t transfer_type;
     54        union {
     55                usbhc_iface_transfer_in_callback_t callback_in;
     56                usbhc_iface_transfer_out_callback_t callback_out;
     57        };
    4858        void *arg;
     59        char *buffer;
     60        char *packet;
    4961        size_t buffer_size;
    50         size_t actual_size;
     62        size_t max_packet_size;
     63        size_t packet_size;
     64        size_t buffer_offset;
     65        dev_speed_t speed;
    5166        device_t *dev;
    52 } callback_t;
     67        transfer_descriptor_t *td;
     68        void (*next_step)(struct tracker*);
     69        unsigned toggle:1;
     70} tracker_t;
    5371
    5472
    55 int callback_init(callback_t *instance, device_t *dev,
    56   void *buffer, size_t size, usbhc_iface_transfer_in_callback_t func_in,
    57   usbhc_iface_transfer_out_callback_t func_out, void *arg);
     73tracker_t * tracker_get(device_t *dev, usb_target_t target,
     74    usb_transfer_type_t transfer_type, size_t max_packet_size,
     75    dev_speed_t speed, char *buffer, size_t size,
     76    usbhc_iface_transfer_in_callback_t func_in,
     77    usbhc_iface_transfer_out_callback_t func_out, void *arg);
    5878
    59 #define callback_in_init(instance, dev, buffer, size, func, arg) \
    60         callback_init(instance, dev, buffer, size, func, NULL, arg)
     79void tracker_control_write(
     80    tracker_t *instance, char* setup_buffer, size_t setup_size);
    6181
    62 #define callback_out_init(instance, dev, buffer, size, func, arg) \
    63         callback_init(instance, dev, buffer, size, func, NULL, arg)
     82void tracker_control_read(
     83    tracker_t *instance, char* setup_buffer, size_t setup_size);
    6484
    65 static inline callback_t *callback_get(device_t *dev,
    66   void *buffer, size_t size, usbhc_iface_transfer_in_callback_t func_in,
    67   usbhc_iface_transfer_out_callback_t func_out, void *arg)
    68 {
    69         callback_t *instance = malloc(sizeof(callback_t));
    70         if (callback_init(instance, dev, buffer, size, func_in, func_out, arg)) {
    71                 free(instance);
    72                 instance = NULL;
    73         }
    74         return instance;
    75 }
     85void tracker_interrupt_in(tracker_t *instance);
    7686
    77 static inline void callback_fini(callback_t *instance)
    78 {
    79         assert(instance);
    80         if (instance->new_buffer)
    81                 free32(instance->new_buffer);
    82 }
     87void tracker_interrupt_out(tracker_t *instance);
    8388
    84 static inline void callback_dispose(callback_t *instance)
    85 {
    86         callback_fini(instance);
    87         free(instance);
    88 }
     89/* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
     90void tracker_control_setup_old(tracker_t *instance);
    8991
    90 void callback_run(
    91   callback_t *instance, usb_transaction_outcome_t outcome, size_t act_size);
     92void tracker_control_write_data_old(tracker_t *instance);
     93
     94void tracker_control_read_data_old(tracker_t *instance);
     95
     96void tracker_control_write_status_old(tracker_t *instance);
     97
     98void tracker_control_read_status_old(tracker_t *instance);
    9299#endif
    93100/**
  • uspace/drv/uhci-hcd/transfer_list.c

    r960ff451 r5d4193c  
    4141{
    4242        assert(instance);
    43         instance->first = NULL;
    44         instance->last = NULL;
    4543        instance->next = NULL;
    4644        instance->name = name;
     
    6664}
    6765/*----------------------------------------------------------------------------*/
    68 int transfer_list_append(
    69   transfer_list_t *instance, transfer_descriptor_t *transfer)
     66void transfer_list_add_tracker(transfer_list_t *instance, tracker_t *tracker)
    7067{
    7168        assert(instance);
    72         assert(transfer);
     69        assert(tracker);
    7370
    74         uint32_t pa = (uintptr_t)addr_to_phys(transfer);
     71        uint32_t pa = (uintptr_t)addr_to_phys(tracker->td);
    7572        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
    7673
    77         /* empty list */
    78         if (instance->first == NULL) {
    79                 assert(instance->last == NULL);
    80                 instance->first = instance->last = transfer;
    81         } else {
    82                 assert(instance->last);
    83                 instance->last->next_va = transfer;
    8474
    85                 assert(instance->last->next & LINK_POINTER_TERMINATE_FLAG);
    86                 instance->last->next = (pa & LINK_POINTER_ADDRESS_MASK);
    87                 instance->last = transfer;
     75        if (instance->queue_head->element & LINK_POINTER_TERMINATE_FLAG) {
     76                usb_log_debug2("Adding td(%X:%X) to queue %s first.\n",
     77                        tracker->td->status, tracker->td->device, instance->name);
     78                /* there is nothing scheduled */
     79                instance->last_tracker = tracker;
     80                instance->queue_head->element = pa;
     81                usb_log_debug2("Added td(%X:%X) to queue %s first.\n",
     82                        tracker->td->status, tracker->td->device, instance->name);
     83                return;
    8884        }
     85        usb_log_debug2("Adding td(%X:%X) to queue %s last.%p\n",
     86            tracker->td->status, tracker->td->device, instance->name,
     87            instance->last_tracker);
     88        /* now we can be sure that last_tracker is a valid pointer */
     89        instance->last_tracker->td->next = pa;
     90        instance->last_tracker = tracker;
    8991
    90         assert(instance->queue_head);
     92        usb_log_debug2("Added td(%X:%X) to queue %s last.\n",
     93                tracker->td->status, tracker->td->device, instance->name);
     94
     95        /* check again, may be use atomic compare and swap */
    9196        if (instance->queue_head->element & LINK_POINTER_TERMINATE_FLAG) {
    92                 instance->queue_head->element = (pa & LINK_POINTER_ADDRESS_MASK);
     97                instance->queue_head->element = pa;
     98                usb_log_debug2("Added td(%X:%X) to queue first2 %s.\n",
     99                        tracker->td->status, tracker->td->device, instance->name);
    93100        }
    94         usb_log_debug("Successfully added transfer to the hc queue %s.\n",
    95           instance->name);
    96         return EOK;
    97101}
    98102/**
  • uspace/drv/uhci-hcd/transfer_list.h

    r960ff451 r5d4193c  
    3636
    3737#include "uhci_struct/queue_head.h"
    38 #include "uhci_struct/transfer_descriptor.h"
     38#include "tracker.h"
    3939
    4040typedef struct transfer_list
    4141{
    42         transfer_descriptor_t *first;
    43         transfer_descriptor_t *last;
     42        tracker_t *last_tracker;
     43
    4444        queue_head_t *queue_head;
    4545        uint32_t queue_head_pa;
     
    5858}
    5959
    60 int transfer_list_append(
    61   transfer_list_t *instance, transfer_descriptor_t *transfer);
     60
     61void transfer_list_add_tracker(transfer_list_t *instance, tracker_t *tracker);
    6262
    6363#endif
  • uspace/drv/uhci-hcd/uhci.c

    r960ff451 r5d4193c  
    3333 */
    3434#include <errno.h>
     35#include <adt/list.h>
    3536
    3637#include <usb/debug.h>
     
    4243static int uhci_clean_finished(void *arg);
    4344static int uhci_debug_checker(void *arg);
     45static bool allowed_usb_packet(
     46        bool low_speed, usb_transfer_type_t, size_t size);
    4447
    4548int uhci_init(uhci_t *instance, void *regs, size_t reg_size)
     
    8487
    8588        const uintptr_t pa = (uintptr_t)addr_to_phys(instance->frame_list);
    86 
    8789        pio_write_32(&instance->registers->flbaseadd, (uint32_t)pa);
     90
     91        list_initialize(&instance->tracker_list);
     92        fibril_mutex_initialize(&instance->tracker_list_mutex);
    8893
    8994        instance->cleaner = fibril_create(uhci_clean_finished, instance);
     
    9398        fibril_add_ready(instance->debug_checker);
    9499
    95         /* Start the hc with large(64b) packet FSBR */
     100        /* Start the hc with large(64B) packet FSBR */
    96101        pio_write_16(&instance->registers->usbcmd,
    97102            UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET);
     
    147152}
    148153/*----------------------------------------------------------------------------*/
    149 int uhci_transfer(
    150   uhci_t *instance,
    151   device_t *dev,
    152   usb_target_t target,
    153   usb_transfer_type_t transfer_type,
    154         bool toggle,
    155   usb_packet_id pid,
    156         bool low_speed,
    157   void *buffer, size_t size,
    158   usbhc_iface_transfer_out_callback_t callback_out,
    159   usbhc_iface_transfer_in_callback_t callback_in,
    160   void *arg)
    161 {
    162         // TODO: Add support for isochronous transfers
    163         if (transfer_type == USB_TRANSFER_ISOCHRONOUS) {
    164                 usb_log_warning("ISO transfer not supported.\n");
     154int uhci_schedule(uhci_t *instance, tracker_t *tracker)
     155{
     156        assert(instance);
     157        assert(tracker);
     158        const int low_speed = (tracker->speed == LOW_SPEED);
     159        if (!allowed_usb_packet(
     160            low_speed, tracker->transfer_type, tracker->packet_size)) {
     161                usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n",
     162                          low_speed ? "LOW" : "FULL" , tracker->transfer_type,
     163                    tracker->packet_size);
    165164                return ENOTSUP;
    166165        }
    167 
    168         if (transfer_type == USB_TRANSFER_INTERRUPT
    169           && size >= 64) {
    170                 usb_log_warning("Interrupt transfer too big %zu.\n", size);
    171                 return ENOTSUP;
    172         }
    173 
    174         if (size >= 1024) {
    175                 usb_log_warning("Transfer too big.\n");
    176                 return ENOTSUP;
    177         }
    178         transfer_list_t *list = instance->transfers[low_speed][transfer_type];
    179         if (!list) {
    180                 usb_log_warning("UNSUPPORTED transfer %d-%d.\n", low_speed, transfer_type);
    181                 return ENOTSUP;
    182         }
    183 
    184         transfer_descriptor_t *td = NULL;
    185         callback_t *job = NULL;
    186         int ret = EOK;
    187         assert(dev);
    188 
    189 #define CHECK_RET_TRANS_FREE_JOB_TD(message) \
    190         if (ret != EOK) { \
    191                 usb_log_error(message); \
    192                 if (job) { \
    193                         callback_dispose(job); \
    194                 } \
    195                 if (td) { free32(td); } \
    196                 return ret; \
    197         } else (void) 0
    198 
    199         job = callback_get(dev, buffer, size, callback_in, callback_out, arg);
    200         ret = job ? EOK : ENOMEM;
    201         CHECK_RET_TRANS_FREE_JOB_TD("Failed to allocate callback structure.\n");
    202 
    203         td = transfer_descriptor_get(3, size, false, target, pid, job->new_buffer);
    204         ret = td ? EOK : ENOMEM;
    205         CHECK_RET_TRANS_FREE_JOB_TD("Failed to setup transfer descriptor.\n");
    206 
    207         td->callback = job;
    208 
    209 
    210         usb_log_debug("Appending a new transfer to queue %s.\n", list->name);
    211 
    212         ret = transfer_list_append(list, td);
    213         CHECK_RET_TRANS_FREE_JOB_TD("Failed to append transfer descriptor.\n");
     166        /* TODO: check available bandwith here */
     167
     168        usb_log_debug2("Scheduler(%d) acquiring tracker list mutex.\n",
     169            fibril_get_id());
     170        fibril_mutex_lock(&instance->tracker_list_mutex);
     171        usb_log_debug2("Scheduler(%d) acquired tracker list mutex.\n",
     172            fibril_get_id());
     173
     174        transfer_list_t *list =
     175            instance->transfers[low_speed][tracker->transfer_type];
     176        assert(list);
     177        transfer_list_add_tracker(list, tracker);
     178        list_append(&tracker->link, &instance->tracker_list);
     179
     180        usb_log_debug2("Scheduler(%d) releasing tracker list mutex.\n",
     181            fibril_get_id());
     182        fibril_mutex_unlock(&instance->tracker_list_mutex);
     183        usb_log_debug2("Scheduler(%d) released tracker list mutex.\n",
     184            fibril_get_id());
    214185
    215186        return EOK;
    216187}
    217 /*---------------------------------------------------------------------------*/
     188/*----------------------------------------------------------------------------*/
    218189int uhci_clean_finished(void* arg)
    219190{
     
    223194
    224195        while(1) {
    225                 usb_log_debug("Running cleaning fibril on: %p.\n", instance);
    226                 /* iterate all transfer queues */
    227                 transfer_list_t *current_list = &instance->transfers_interrupt;
    228                 while (current_list) {
    229                         /* Remove inactive transfers from the top of the queue
    230                          * TODO: should I reach queue head or is this enough? */
    231                         volatile transfer_descriptor_t * it =
    232                                 current_list->first;
    233                         usb_log_debug("Running cleaning fibril on queue: %s (%s).\n",
    234                                 current_list->name, it ? "SOMETHING" : "EMPTY");
    235 
    236                         if (it) {
    237                                 usb_log_debug("First in queue: %p (%x) PA:%x.\n",
    238                                         it, it->status, addr_to_phys((void*)it) );
    239                                 usb_log_debug("First to send: %x\n",
    240                                         (current_list->queue_head->element) );
     196                LIST_INITIALIZE(done_trackers);
     197                /* tracker iteration */
     198
     199                usb_log_debug2("Cleaner(%d) acquiring tracker list mutex.\n",
     200                    fibril_get_id());
     201                fibril_mutex_lock(&instance->tracker_list_mutex);
     202                usb_log_debug2("Cleaner(%d) acquired tracker list mutex.\n",
     203                    fibril_get_id());
     204
     205                link_t *current = instance->tracker_list.next;
     206                while (current != &instance->tracker_list)
     207                {
     208
     209                        link_t *next = current->next;
     210                        tracker_t *tracker = list_get_instance(current, tracker_t, link);
     211
     212                        assert(current == &tracker->link);
     213                        assert(tracker);
     214                        assert(tracker->next_step);
     215                        assert(tracker->td);
     216
     217                        if (!transfer_descriptor_is_active(tracker->td)) {
     218                                usb_log_info("Found inactive tracker with status: %x:%x.\n",
     219                                    tracker->td->status, tracker->td->device);
     220                                list_remove(current);
     221                                list_append(current, &done_trackers);
    241222                        }
    242 
    243                         while (current_list->first &&
    244                          !(current_list->first->status & TD_STATUS_ERROR_ACTIVE)) {
    245                                 transfer_descriptor_t *transfer = current_list->first;
    246                                 usb_log_info("Inactive transfer calling callback with status %x.\n",
    247                                   transfer->status);
    248                                 current_list->first = transfer->next_va;
    249                                 transfer_descriptor_dispose(transfer);
    250                         }
    251                         if (!current_list->first)
    252                                 current_list->last = current_list->first;
    253 
    254                         current_list = current_list->next;
     223                        current = next;
     224                }
     225
     226                usb_log_debug2("Cleaner(%d) releasing tracker list mutex.\n",
     227                    fibril_get_id());
     228                fibril_mutex_unlock(&instance->tracker_list_mutex);
     229                usb_log_debug2("Cleaner(%d) released tracker list mutex.\n",
     230                    fibril_get_id());
     231
     232                while (!list_empty(&done_trackers)) {
     233                        tracker_t *tracker = list_get_instance(
     234                          done_trackers.next, tracker_t, link);
     235                        list_remove(&tracker->link);
     236                        tracker->next_step(tracker);
    255237                }
    256238                async_usleep(UHCI_CLEANER_TIMEOUT);
     
    311293        return 0;
    312294}
     295/*----------------------------------------------------------------------------*/
     296bool allowed_usb_packet(
     297        bool low_speed, usb_transfer_type_t transfer, size_t size)
     298{
     299        /* see USB specification chapter 5.5-5.8 for magic numbers used here */
     300        switch(transfer) {
     301                case USB_TRANSFER_ISOCHRONOUS:
     302                        return (!low_speed && size < 1024);
     303                case USB_TRANSFER_INTERRUPT:
     304                        return size <= (low_speed ? 8 : 64);
     305                case USB_TRANSFER_CONTROL: /* device specifies its own max size */
     306                        return (size <= (low_speed ? 8 : 64));
     307                case USB_TRANSFER_BULK: /* device specifies its own max size */
     308                        return (!low_speed && size <= 64);
     309        }
     310        return false;
     311}
    313312/**
    314313 * @}
  • uspace/drv/uhci-hcd/uhci.h

    r960ff451 r5d4193c  
    3737
    3838#include <fibril.h>
     39#include <fibril_synch.h>
     40#include <adt/list.h>
    3941
    4042#include <usb/addrkeep.h>
     
    4244
    4345#include "transfer_list.h"
     46#include "tracker.h"
    4447
    4548typedef struct uhci_regs {
     
    6871} regs_t;
    6972
    70 #define TRANSFER_QUEUES 4
    7173#define UHCI_FRAME_LIST_COUNT 1024
    7274#define UHCI_CLEANER_TIMEOUT 10000
    73 #define UHCI_DEBUGER_TIMEOUT 500000
     75#define UHCI_DEBUGER_TIMEOUT 5000000
    7476
    7577typedef struct uhci {
     
    7880
    7981        link_pointer_t *frame_list;
     82
     83        link_t tracker_list;
     84        fibril_mutex_t tracker_list_mutex;
    8085
    8186        transfer_list_t transfers_bulk_full;
     
    108113  void *arg );
    109114
     115int uhci_schedule(uhci_t *instance, tracker_t *tracker);
     116
    110117static inline uhci_t * dev_to_uhci(device_t *dev)
    111118        { return (uhci_t*)dev->driver_data; }
  • uspace/drv/uhci-hcd/uhci_struct/queue_head.h

    r960ff451 r5d4193c  
    4343
    4444typedef struct queue_head {
    45         link_pointer_t next_queue;
    46         link_pointer_t element;
     45        volatile link_pointer_t next_queue;
     46        volatile link_pointer_t element;
    4747} __attribute__((packed)) queue_head_t;
    4848
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c

    r960ff451 r5d4193c  
    3232 * @brief UHCI driver
    3333 */
     34#include <errno.h>
    3435#include <usb/debug.h>
    3536
    3637#include "transfer_descriptor.h"
     38#include "utils/malloc32.h"
    3739
    3840void transfer_descriptor_init(transfer_descriptor_t *instance,
    39   int error_count, size_t size, bool isochronous, usb_target_t target,
    40         int pid, void *buffer)
     41    int error_count, size_t size, bool toggle, bool isochronous,
     42    usb_target_t target, int pid, void *buffer)
    4143{
    4244        assert(instance);
    4345
    44         instance->next =
    45           0 | LINK_POINTER_TERMINATE_FLAG;
     46        instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
    4647
    47 
    48         assert(size < 1024);
    4948        instance->status = 0
    5049          | ((error_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
    5150          | TD_STATUS_ERROR_ACTIVE;
    5251
     52        assert(size < 1024);
    5353        instance->device = 0
    5454                | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
     55                | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
    5556                | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
    5657                | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
     
    5859
    5960        instance->buffer_ptr = 0;
    60 
    61         instance->next_va = NULL;
    62         instance->callback = NULL;
    6361
    6462        if (size) {
     
    106104                return USB_OUTCOME_CRCERROR;
    107105
    108         assert((((status >> TD_STATUS_ERROR_POS) & TD_STATUS_ERROR_MASK)
    109         | TD_STATUS_ERROR_RESERVED) == TD_STATUS_ERROR_RESERVED);
     106//      assert((((status >> TD_STATUS_ERROR_POS) & TD_STATUS_ERROR_MASK)
     107//      | TD_STATUS_ERROR_RESERVED) == TD_STATUS_ERROR_RESERVED);
    110108        return USB_OUTCOME_OK;
    111109}
    112 
    113 void transfer_descriptor_fini(transfer_descriptor_t *instance)
     110/*----------------------------------------------------------------------------*/
     111int transfer_descriptor_status(transfer_descriptor_t *instance)
    114112{
    115113        assert(instance);
    116         callback_run(instance->callback,
    117                 convert_outcome(instance->status),
    118                 ((instance->status >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK
    119         );
     114        if (convert_outcome(instance->status))
     115                return EINVAL; //TODO: use sane error value here
     116        return EOK;
    120117}
    121118/**
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h

    r960ff451 r5d4193c  
    3838#include <usb/usb.h>
    3939
    40 #include "utils/malloc32.h"
    41 #include "callback.h"
    4240#include "link_pointer.h"
    4341
     
    8684        volatile uint32_t buffer_ptr;
    8785
    88         /* there is 16 bytes of data available here
    89          * those are used to store callback pointer
    90          * and next pointer. Thus, there is some free space
    91          * on 32bits systems.
     86        /* there is 16 bytes of data available here, according to UHCI
     87         * Design guide, according to linux kernel the hardware does not care
     88         * we don't use it anyway
    9289         */
    93         struct transfer_descriptor *next_va;
    94         callback_t *callback;
    9590} __attribute__((packed)) transfer_descriptor_t;
    9691
    9792
    9893void transfer_descriptor_init(transfer_descriptor_t *instance,
    99   int error_count, size_t size, bool isochronous, usb_target_t target,
    100         int pid, void *buffer);
     94    int error_count, size_t size, bool toggle, bool isochronous,
     95    usb_target_t target, int pid, void *buffer);
    10196
    102 static inline transfer_descriptor_t * transfer_descriptor_get(
    103   int error_count, size_t size, bool isochronous, usb_target_t target,
    104   int pid, void *buffer)
    105 {
    106         transfer_descriptor_t * instance =
    107           malloc32(sizeof(transfer_descriptor_t));
     97int transfer_descriptor_status(transfer_descriptor_t *instance);
    10898
    109         if (instance)
    110                 transfer_descriptor_init(
    111                   instance, error_count, size, isochronous, target, pid, buffer);
    112         return instance;
    113 }
    114 
    115 void transfer_descriptor_fini(transfer_descriptor_t *instance);
    116 
    117 static inline void transfer_descriptor_dispose(transfer_descriptor_t *instance)
     99static inline bool transfer_descriptor_is_active(
     100    transfer_descriptor_t *instance)
    118101{
    119102        assert(instance);
    120         transfer_descriptor_fini(instance);
    121         free32(instance);
    122 }
    123 
    124 static inline void transfer_descriptor_append(
    125   transfer_descriptor_t *instance, transfer_descriptor_t *item)
    126 {
    127         assert(instance);
    128         instance->next_va = item;
    129         instance->next = (uintptr_t)addr_to_phys( item ) & LINK_POINTER_ADDRESS_MASK;
     103        return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
    130104}
    131105#endif
  • uspace/drv/uhci-rhd/main.c

    r960ff451 r5d4193c  
    102102int main(int argc, char *argv[])
    103103{
    104         usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
     104        usb_log_enable(USB_LOG_LEVEL_ERROR, NAME);
    105105        return driver_main(&uhci_rh_driver);
    106106}
Note: See TracChangeset for help on using the changeset viewer.