Changeset 7dd3318 in mainline


Ignore:
Timestamp:
2011-02-12T02:00:54Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
83c439c
Parents:
f6309b6
Message:

Add support for batch processing

Location:
uspace/drv/uhci-hcd
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/uhci-hcd/iface.c

    rf6309b6 r7dd3318  
    110110
    111111        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_INTERRUPT,
    112             max_packet_size, speed, data, size, NULL, callback, arg);
     112            max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg);
    113113        if (!tracker)
    114114                return ENOMEM;
     
    125125
    126126        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_INTERRUPT,
    127             max_packet_size, speed, data, size, callback, NULL, arg);
     127            max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg);
    128128        if (!tracker)
    129129                return ENOMEM;
     
    140140
    141141        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);
     142            max_packet_size, speed, data, size, setup_data, setup_size,
     143            NULL, callback, arg);
     144        if (!tracker)
     145                return ENOMEM;
     146        tracker_control_write(tracker);
    146147        return EOK;
    147148}
     
    155156
    156157        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);
     158            max_packet_size, speed, data, size, setup_data, setup_size, callback,
     159            NULL, arg);
     160        if (!tracker)
     161                return ENOMEM;
     162        tracker_control_read(tracker);
    161163        return EOK;
    162164}
     
    166168    usbhc_iface_transfer_out_callback_t callback, void *arg)
    167169{
    168         usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
    169         tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
    170             8, FULL_SPEED, data, size, NULL, callback, arg);
     170        size_t max_packet_size = 8;
     171        dev_speed_t speed = FULL_SPEED;
     172
     173        usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
     174        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     175            max_packet_size, speed, NULL, 0, data, size, NULL, callback, arg);
    171176        if (!tracker)
    172177                return ENOMEM;
     
    179184    usbhc_iface_transfer_out_callback_t callback, void *arg)
    180185{
    181         usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
    182         tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
    183             size, FULL_SPEED, data, size, NULL, callback, arg);
     186        size_t max_packet_size = 8;
     187        dev_speed_t speed = FULL_SPEED;
     188
     189        usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
     190        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     191            max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg);
    184192        if (!tracker)
    185193                return ENOMEM;
     
    191199    usbhc_iface_transfer_in_callback_t callback, void *arg)
    192200{
    193         usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
    194         tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
    195             0, FULL_SPEED, NULL, 0, callback, NULL, arg);
     201        size_t max_packet_size = 8;
     202        dev_speed_t speed = FULL_SPEED;
     203
     204        usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
     205        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     206            max_packet_size, speed, NULL, 0, NULL, 0, callback, NULL, arg);
    196207        if (!tracker)
    197208                return ENOMEM;
     
    204215    usbhc_iface_transfer_out_callback_t callback, void *arg)
    205216{
    206         usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
    207         tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
    208             8, FULL_SPEED, data, size, NULL, callback, arg);
     217        size_t max_packet_size = 8;
     218        dev_speed_t speed = FULL_SPEED;
     219
     220        usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
     221        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     222            max_packet_size, speed, NULL, 0, data, size, NULL, callback, arg);
    209223        if (!tracker)
    210224                return ENOMEM;
     
    217231    usbhc_iface_transfer_in_callback_t callback, void *arg)
    218232{
    219         usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
    220         tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
    221             size, FULL_SPEED, data, size, callback, NULL, arg);
     233        size_t max_packet_size = 8;
     234        dev_speed_t speed = FULL_SPEED;
     235
     236        usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
     237        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     238            max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg);
    222239        if (!tracker)
    223240                return ENOMEM;
     
    229246    usbhc_iface_transfer_out_callback_t callback, void *arg)
    230247{
    231         usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
    232         tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
    233             0, FULL_SPEED, NULL, 0, NULL, callback, arg);
     248        size_t max_packet_size = 8;
     249        dev_speed_t speed = FULL_SPEED;
     250
     251        usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
     252        tracker_t *tracker = tracker_get(dev, target, USB_TRANSFER_CONTROL,
     253            max_packet_size, speed, NULL, 0, NULL, 0, NULL, callback, arg);
    234254        if (!tracker)
    235255                return ENOMEM;
  • uspace/drv/uhci-hcd/main.c

    rf6309b6 r7dd3318  
    134134         */
    135135        sleep(5);
    136         usb_log_enable(USB_LOG_LEVEL_INFO, NAME);
     136        usb_log_enable(USB_LOG_LEVEL_DEBUG2, NAME);
    137137
    138138        return driver_main(&uhci_driver);
  • uspace/drv/uhci-hcd/tracker.c

    rf6309b6 r7dd3318  
    4141#include "utils/malloc32.h"
    4242
    43 #define SETUP_PACKET_DATA_SIZE 8
    4443#define DEFAULT_ERROR_COUNT 3
    45 #define MAX(a,b) ((a > b) ? a : b)
    46 #define MIN(a,b) ((a < b) ? a : b)
    4744
    4845static int tracker_schedule(tracker_t *instance);
    49 
    50 static void tracker_control_read_data(tracker_t *instance);
    51 static void tracker_control_write_data(tracker_t *instance);
    52 static void tracker_control_read_status(tracker_t *instance);
    53 static void tracker_control_write_status(tracker_t *instance);
    5446
    5547static void tracker_call_in(tracker_t *instance);
     
    6254    usb_transfer_type_t transfer_type, size_t max_packet_size,
    6355    dev_speed_t speed, char *buffer, size_t size,
     56    char* setup_buffer, size_t setup_size,
    6457    usbhc_iface_transfer_in_callback_t func_in,
    6558    usbhc_iface_transfer_out_callback_t func_out, void *arg)
     
    6962
    7063        tracker_t *instance = malloc(sizeof(tracker_t));
    71         if (!instance) {
    72                 usb_log_error("Failed to allocate tracker isntance.\n");
    73                 return NULL;
    74         }
    75 
    76         instance->td = malloc32(sizeof(transfer_descriptor_t));
    77         if (!instance->td) {
    78                 usb_log_error("Failed to allocate transfer descriptor.\n");
     64        if (instance == NULL) {
     65                usb_log_error("Failed to allocate tracker instance.\n");
     66                return NULL;
     67        }
     68
     69        instance->qh = queue_head_get();
     70        if (instance->qh == NULL) {
     71                usb_log_error("Failed to allocate queue head.\n");
    7972                free(instance);
    8073                return NULL;
    8174        }
    82         bzero(instance->td, sizeof(transfer_descriptor_t));
    83 
    84         instance->packet = max_packet_size ? malloc32(max_packet_size) : NULL;
    85         if (max_packet_size && !instance->packet) {
    86                 usb_log_error("Failed to allocate device acessible buffer.\n");
    87                 free32(instance->td);
     75
     76        instance->packets = (size + max_packet_size - 1) / max_packet_size;
     77        if (transfer_type == USB_TRANSFER_CONTROL) {
     78                instance->packets += 2;
     79        }
     80
     81        instance->tds = malloc32(sizeof(transfer_descriptor_t) * instance->packets);
     82        if (instance->tds == NULL) {
     83                usb_log_error("Failed to allocate transfer descriptors.\n");
     84                queue_head_dispose(instance->qh);
    8885                free(instance);
    8986                return NULL;
    9087        }
     88        bzero(instance->tds, sizeof(transfer_descriptor_t) * instance->packets);
     89
     90        const size_t transport_size = max_packet_size * instance->packets;
     91
     92        instance->transport_buffer =
     93           (size > 0) ? malloc32(transport_size) : NULL;
     94        if ((size > 0) && (instance->transport_buffer == NULL)) {
     95                usb_log_error("Failed to allocate device accessible buffer.\n");
     96                queue_head_dispose(instance->qh);
     97                free32(instance->tds);
     98                free(instance);
     99                return NULL;
     100        }
     101
     102        instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL;
     103        if ((setup_size > 0) && (instance->setup_buffer == NULL)) {
     104                usb_log_error("Failed to allocate device accessible setup buffer.\n");
     105                queue_head_dispose(instance->qh);
     106                free32(instance->tds);
     107                free32(instance->transport_buffer);
     108                free(instance);
     109                return NULL;
     110        }
     111        if (instance->setup_buffer) {
     112                memcpy(instance->setup_buffer, setup_buffer, setup_size);
     113        }
     114
    91115        instance->max_packet_size = max_packet_size;
    92         instance->packet_size = 0;
    93         instance->buffer_offset = 0;
    94116
    95117        link_initialize(&instance->link);
     118
    96119        instance->target = target;
    97120        instance->transfer_type = transfer_type;
     
    101124        if (func_in)
    102125                instance->callback_in = func_in;
     126
    103127        instance->buffer = buffer;
    104128        instance->buffer_size = size;
     129        instance->setup_size = setup_size;
    105130        instance->dev = dev;
    106131        instance->arg = arg;
    107         instance->toggle = 0;
    108132        instance->speed = speed;
    109133
     134        queue_head_element_td(instance->qh, addr_to_phys(instance->tds));
    110135        return instance;
    111136}
    112137/*----------------------------------------------------------------------------*/
    113 void tracker_control_write(
    114     tracker_t *instance, char* setup_buffer, size_t setup_size)
    115 {
    116         assert(instance);
    117         assert(instance->buffer_offset == 0);
    118         assert(setup_size == 8);
    119 
    120         instance->packet_size = 0;
    121         memcpy(instance->packet, setup_buffer, setup_size);
    122 
    123         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    124             setup_size, instance->toggle++, false, instance->target,
    125             USB_PID_SETUP, instance->packet);
    126 
    127         instance->next_step = tracker_control_write_data;
    128 
    129         tracker_schedule(instance);
    130 }
    131 /*----------------------------------------------------------------------------*/
    132 void tracker_control_read(
    133     tracker_t *instance, char* setup_buffer, size_t setup_size)
    134 {
    135         assert(instance);
    136         assert(instance->buffer_offset == 0);
    137         assert(setup_size == 8);
    138 
    139         memcpy(instance->packet, setup_buffer, setup_size);
    140 
    141         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    142             setup_size, instance->toggle++, false, instance->target,
    143             USB_PID_SETUP, instance->packet);
    144 
    145         instance->next_step = tracker_control_read_data;
    146 
    147         tracker_schedule(instance);
    148 }
    149 /*----------------------------------------------------------------------------*/
    150 void tracker_control_read_data(tracker_t *instance)
    151 {
    152         assert(instance);
    153 
    154         /* check for errors */
    155         int err = transfer_descriptor_status(instance->td);
    156         if (err != EOK) {
    157                 tracker_call_in_and_dispose(instance);
    158                 return;
    159         }
    160 
    161         /* we are data in, we want data from our device */
    162         if (instance->packet_size) {
    163                 memcpy(instance->buffer + instance->buffer_offset, instance->packet,
    164                     instance->packet_size);
    165         }
    166         instance->buffer_offset += instance->packet_size;
    167 
    168         /* prepare next packet, no copy, we are receiving data */
    169         instance->packet_size = MIN(instance->max_packet_size,
    170             instance->buffer_size - instance->buffer_offset);
    171 
    172         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    173             instance->packet_size, instance->toggle++, false, instance->target,
    174             USB_PID_IN, instance->packet);
    175 
    176         tracker_schedule(instance);
    177 
    178         /* set next step */
    179         if ((instance->buffer_offset + instance->packet_size)
    180             >= instance->buffer_size) {
    181                 /* that's all, end coomunication */
    182                 instance->next_step = tracker_control_read_status;
    183         }
    184 }
    185 /*----------------------------------------------------------------------------*/
    186 void tracker_control_write_data(tracker_t *instance)
    187 {
    188         assert(instance);
    189 
    190         /* check for errors */
    191         int err = transfer_descriptor_status(instance->td);
    192         if (err != EOK) {
    193                 tracker_call_out_and_dispose(instance);
    194                 return;
    195         }
    196 
    197         /* we are data out, we don't want data from our device */
    198         instance->buffer_offset += instance->packet_size;
    199 
    200         /* prepare next packet, copy data to packet */
    201         instance->packet_size = MIN(instance->max_packet_size,
    202             instance->buffer_size - instance->buffer_offset);
    203         memcpy(instance->packet, instance->buffer + instance->buffer_offset,
    204             instance->packet_size);
    205 
    206         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    207             instance->packet_size, instance->toggle++, false, instance->target,
    208             USB_PID_OUT, instance->packet);
    209 
    210         tracker_schedule(instance);
    211 
    212         /* set next step */
    213         if ((instance->buffer_offset + instance->packet_size)
    214             >= instance->buffer_size) {
    215                 /* that's all, end coomunication */
    216                 instance->next_step = tracker_control_write_status;
    217         }
    218 }
    219 /*----------------------------------------------------------------------------*/
    220 void tracker_control_read_status(tracker_t *instance)
    221 {
    222         assert(instance);
    223 
    224         /* check for errors */
    225         int err = transfer_descriptor_status(instance->td);
    226         if (err != EOK) {
    227                 tracker_call_in_and_dispose(instance);
    228                 return;
    229         }
    230 
    231         /* we are data in, we want data from our device */
    232         memcpy(instance->buffer + instance->buffer_offset, instance->packet,
    233             instance->packet_size);
    234         instance->buffer_offset += instance->packet_size;
    235         assert(instance->buffer_offset = instance->buffer_size);
    236 
    237         /* prepare next packet, no nothing, just an empty packet */
    238         instance->packet_size = 0;
    239         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    240             instance->packet_size, 1, false, instance->target, USB_PID_OUT, NULL);
    241 
    242         tracker_schedule(instance);
    243 
    244         /* set next step, callback and cleanup */
     138bool tracker_is_complete(tracker_t *instance)
     139{
     140        assert(instance);
     141        usb_log_debug("Checking(%p) %d packet for completion.\n",
     142            instance, instance->packets);
     143        /* This is just an ugly trick to support the old API */
     144        instance->transfered_size = -instance->setup_size;
     145        size_t i = 0;
     146        for (;i < instance->packets; ++i) {
     147                if (transfer_descriptor_is_active(&instance->tds[i]))
     148                        return false;
     149                instance->error = transfer_descriptor_status(&instance->tds[i]);
     150                if (instance->error != EOK) {
     151                        return true;
     152                }
     153                instance->transfered_size +=
     154                    transfer_descriptor_actual_size(&instance->tds[i]);
     155        }
     156        return true;
     157}
     158/*----------------------------------------------------------------------------*/
     159void tracker_control_write(tracker_t *instance)
     160{
     161        assert(instance);
     162
     163        /* we are data out, we are supposed to provide data */
     164        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
     165
     166        int toggle = 0;
     167        /* setup stage */
     168        transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
     169            instance->setup_size, toggle, false, instance->target,
     170            USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
     171
     172        /* data stage */
     173        size_t i = 1;
     174        for (;i < instance->packets - 1; ++i) {
     175                char *data =
     176                    instance->transport_buffer + ((i - 1) * instance->max_packet_size);
     177                toggle = 1 - toggle;
     178
     179                transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
     180                    instance->max_packet_size, toggle++, false, instance->target,
     181                    USB_PID_OUT, data, &instance->tds[i + 1]);
     182        }
     183
     184        /* status stage */
     185        i = instance->packets - 1;
     186        transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
     187            0, 1, false, instance->target, USB_PID_IN, NULL, NULL);
     188
     189        instance->next_step = tracker_call_out_and_dispose;
     190        tracker_schedule(instance);
     191}
     192/*----------------------------------------------------------------------------*/
     193void tracker_control_read(tracker_t *instance)
     194{
     195        assert(instance);
     196
     197        int toggle = 0;
     198        /* setup stage */
     199        transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
     200            instance->setup_size, toggle, false, instance->target,
     201            USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
     202
     203        /* data stage */
     204        size_t i = 1;
     205        for (;i < instance->packets - 1; ++i) {
     206                char *data =
     207                    instance->transport_buffer + ((i - 1) * instance->max_packet_size);
     208                toggle = 1 - toggle;
     209
     210                transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
     211                    instance->max_packet_size, toggle, false, instance->target,
     212                    USB_PID_IN, data, &instance->tds[i + 1]);
     213        }
     214
     215        /* status stage */
     216        i = instance->packets - 1;
     217        transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
     218            0, 1, false, instance->target, USB_PID_OUT, NULL, NULL);
     219
    245220        instance->next_step = tracker_call_in_and_dispose;
    246 }
    247 /*----------------------------------------------------------------------------*/
    248 void tracker_control_write_status(tracker_t *instance)
    249 {
    250         assert(instance);
    251 
    252         /* check for errors */
    253         int err = transfer_descriptor_status(instance->td);
    254         if (err != EOK) {
    255                 tracker_call_out_and_dispose(instance);
    256                 return;
    257         }
    258 
    259         /* we are data in, we want data from our device */
    260         assert(
    261             instance->buffer_offset + instance->packet_size <= instance->buffer_size);
    262         memcpy(instance->buffer + instance->buffer_offset, instance->packet,
    263             instance->packet_size);
    264         instance->buffer_offset += instance->packet_size;
    265         assert(instance->buffer_offset = instance->buffer_size);
    266 
    267         /* prepare next packet, no nothing, just an empty packet */
    268         instance->packet_size = 0;
    269         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    270             instance->packet_size, 1, false, instance->target, USB_PID_IN, NULL);
    271 
    272         tracker_schedule(instance);
    273 
    274         /* set next step, callback and cleanup */
     221        tracker_schedule(instance);
     222}
     223/*----------------------------------------------------------------------------*/
     224void tracker_interrupt_in(tracker_t *instance)
     225{
     226        assert(instance);
     227
     228        int toggle = 1;
     229        size_t i = 0;
     230        for (;i < instance->packets; ++i) {
     231                char *data =
     232                    instance->transport_buffer + (i  * instance->max_packet_size);
     233                transfer_descriptor_t *next = (i + 1) < instance->packets ?
     234                    &instance->tds[i + 1] : NULL;
     235                toggle = 1 - toggle;
     236
     237                transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
     238                    instance->max_packet_size, toggle, false, instance->target,
     239                    USB_PID_IN, data, next);
     240        }
     241
     242        instance->next_step = tracker_call_in_and_dispose;
     243        tracker_schedule(instance);
     244}
     245/*----------------------------------------------------------------------------*/
     246void tracker_interrupt_out(tracker_t *instance)
     247{
     248        assert(instance);
     249
     250        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
     251
     252        int toggle = 1;
     253        size_t i = 0;
     254        for (;i < instance->packets; ++i) {
     255                char *data =
     256                    instance->transport_buffer + (i  * instance->max_packet_size);
     257                transfer_descriptor_t *next = (i + 1) < instance->packets ?
     258                    &instance->tds[i + 1] : NULL;
     259                toggle = 1 - toggle;
     260
     261                transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
     262                    instance->max_packet_size, toggle++, false, instance->target,
     263                    USB_PID_OUT, data, next);
     264        }
     265
    275266        instance->next_step = tracker_call_out_and_dispose;
    276 }
    277 /*----------------------------------------------------------------------------*/
    278 void tracker_interrupt_in(tracker_t *instance)
    279 {
    280         assert(instance);
    281 
    282         /* check for errors */
    283         int err = transfer_descriptor_status(instance->td);
    284         if (err != EOK) {
    285                 tracker_call_in_and_dispose(instance);
    286                 return;
    287         }
    288 
    289         assert(instance->packet_size <= instance->max_packet_size);
    290         if (instance->packet_size) {
    291                 /* we are data in, we want data from our device. if there is data */
    292                 memcpy(instance->buffer + instance->buffer_offset, instance->packet,
    293                                 instance->packet_size);
    294                 instance->buffer_offset += instance->packet_size;
    295         }
    296 
    297         /* prepare next packet, no copy, we are receiving data */
    298         instance->packet_size = MIN(instance->max_packet_size,
    299                         instance->buffer_size - instance->buffer_offset);
    300         assert(instance->packet_size <= instance->max_packet_size);
    301 
    302         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    303             instance->packet_size, instance->toggle++, false, instance->target,
    304             USB_PID_IN, instance->packet);
    305 
    306         tracker_schedule(instance);
    307 
    308         /* set next step */
    309         if ((instance->buffer_offset + instance->packet_size)
    310             >= instance->buffer_size) {
    311                 /* that's all, end coomunication */
    312                 instance->next_step = tracker_call_in_and_dispose;
    313         } else {
    314                 instance->next_step = tracker_interrupt_in;
    315         }
    316 }
    317 /*----------------------------------------------------------------------------*/
    318 void tracker_interrupt_out(tracker_t *instance)
    319 {
    320         assert(instance);
    321 
    322         /* check for errors */
    323         int err = transfer_descriptor_status(instance->td);
    324         if (err != EOK) {
    325                 tracker_call_out_and_dispose(instance);
    326                 return;
    327         }
    328 
    329         /* we are data out, we don't want data from our device */
    330         instance->buffer_offset += instance->packet_size;
    331 
    332         /* prepare next packet, copy data to packet */
    333         instance->packet_size = MIN(instance->max_packet_size,
    334             instance->buffer_size - instance->buffer_offset);
    335         memcpy(instance->packet, instance->buffer + instance->buffer_offset,
    336             instance->packet_size);
    337 
    338         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    339             instance->packet_size, instance->toggle++, false, instance->target,
    340             USB_PID_OUT, instance->packet);
    341 
    342         tracker_schedule(instance);
    343 
    344         /* set next step */
    345         if ((instance->buffer_offset + instance->packet_size)
    346             >= instance->buffer_size) {
    347                 /* that's all, end coomunication */
    348                 instance->next_step = tracker_call_out_and_dispose;
    349         } else {
    350                 instance->next_step = tracker_interrupt_out;
    351         }
     267        tracker_schedule(instance);
    352268}
    353269/*----------------------------------------------------------------------------*/
     
    357273        assert(instance->callback_in);
    358274
    359         /* check for errors */
    360         int err = transfer_descriptor_status(instance->td);
    361         if (err == EOK && instance->packet_size) {
    362                 memcpy(instance->buffer + instance->buffer_offset, instance->packet,
    363                     instance->packet_size);
    364                 instance->buffer_offset += instance->packet_size;
    365         }
    366         usb_log_debug("Callback IN(%d): %d, %zu.\n", instance->transfer_type,
    367             err, instance->buffer_offset);
     275        memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size);
     276
     277        int err = instance->error;
     278        usb_log_info("Callback IN(%d): %d, %zu.\n", instance->transfer_type,
     279            err, instance->transfered_size);
     280
    368281        instance->callback_in(instance->dev,
    369             err ? USB_OUTCOME_CRCERROR : USB_OUTCOME_OK, instance->buffer_offset,
     282            err, instance->transfered_size,
    370283            instance->arg);
    371284}
     
    376289        assert(instance->callback_out);
    377290
    378         /* check for errors */
    379         int err = transfer_descriptor_status(instance->td);
    380         usb_log_debug("Callback OUT(%d): %d, %zu.\n", instance->transfer_type,
    381             err, instance->buffer_offset);
     291        int err = instance->error;
     292        usb_log_info("Callback OUT(%d): %d.\n", instance->transfer_type, err);
    382293        instance->callback_out(instance->dev,
    383             err ? USB_OUTCOME_CRCERROR : USB_OUTCOME_OK, instance->arg);
     294            err, instance->arg);
    384295}
    385296/*----------------------------------------------------------------------------*/
     
    388299        assert(instance);
    389300        tracker_call_in(instance);
    390         transfer_list_remove_tracker(instance->scheduled_list, instance);
    391         free32(instance->td);
    392         free32(instance->packet);
     301        usb_log_debug("Disposing tracker: %p.\n", instance);
     302        free32(instance->tds);
     303        free32(instance->qh);
     304        free32(instance->setup_buffer);
     305        free32(instance->transport_buffer);
    393306        free(instance);
    394307}
     
    398311        assert(instance);
    399312        tracker_call_out(instance);
    400         assert(instance->scheduled_list);
    401         transfer_list_remove_tracker(instance->scheduled_list, instance);
    402         free32(instance->td);
    403         free32(instance->packet);
     313        usb_log_debug("Disposing tracker: %p.\n", instance);
     314        free32(instance->tds);
     315        free32(instance->qh);
     316        free32(instance->setup_buffer);
     317        free32(instance->transport_buffer);
    404318        free(instance);
    405319}
     
    417331{
    418332        assert(instance);
    419         assert(instance->buffer_offset == 0);
    420 
    421         instance->packet_size = SETUP_PACKET_DATA_SIZE;
    422         memcpy(instance->packet, instance->buffer, SETUP_PACKET_DATA_SIZE);
    423 
    424         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    425             SETUP_PACKET_DATA_SIZE, 0, false, instance->target, USB_PID_SETUP,
    426             instance->packet);
    427 
    428         instance->buffer_offset += SETUP_PACKET_DATA_SIZE;
     333        instance->packets = 1;
     334
     335        /* setup stage */
     336        transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
     337            instance->setup_size, 0, false, instance->target,
     338            USB_PID_SETUP, instance->setup_buffer, NULL);
     339
    429340        instance->next_step = tracker_call_out_and_dispose;
    430 
    431         tracker_schedule(instance);
    432 }
    433 
     341        tracker_schedule(instance);
     342}
     343/*----------------------------------------------------------------------------*/
    434344void tracker_control_write_data_old(tracker_t *instance)
    435345{
    436346        assert(instance);
    437         assert(instance->max_packet_size == instance->buffer_size);
    438 
    439         memcpy(instance->packet, instance->buffer, instance->max_packet_size);
    440         instance->packet_size = instance->max_packet_size;
    441 
    442         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    443             instance->packet_size, 1, false, instance->target, USB_PID_OUT,
    444             instance->packet);
     347        instance->packets -= 2;
     348        tracker_interrupt_out(instance);
     349}
     350/*----------------------------------------------------------------------------*/
     351void tracker_control_read_data_old(tracker_t *instance)
     352{
     353        assert(instance);
     354        instance->packets -= 2;
     355        tracker_interrupt_in(instance);
     356}
     357/*----------------------------------------------------------------------------*/
     358void tracker_control_write_status_old(tracker_t *instance)
     359{
     360        assert(instance);
     361        instance->packets = 1;
     362        transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
     363            0, 1, false, instance->target, USB_PID_IN, NULL, NULL);
     364        instance->next_step = tracker_call_in_and_dispose;
     365        tracker_schedule(instance);
     366}
     367/*----------------------------------------------------------------------------*/
     368void tracker_control_read_status_old(tracker_t *instance)
     369{
     370        assert(instance);
     371        instance->packets = 1;
     372        transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
     373            0, 1, false, instance->target, USB_PID_OUT, NULL, NULL);
    445374        instance->next_step = tracker_call_out_and_dispose;
    446 
    447         tracker_schedule(instance);
    448 }
    449 
    450 void tracker_control_read_data_old(tracker_t *instance)
    451 {
    452         assert(instance);
    453         assert(instance->max_packet_size == instance->buffer_size);
    454 
    455         instance->packet_size = instance->max_packet_size;
    456 
    457         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    458             instance->packet_size, 1, false, instance->target, USB_PID_IN,
    459             instance->packet);
    460 
    461         instance->next_step = tracker_call_in_and_dispose;
    462 
    463         tracker_schedule(instance);
    464 }
    465 
    466 void tracker_control_write_status_old(tracker_t *instance)
    467 {
    468         assert(instance);
    469         assert(instance->max_packet_size == 0);
    470         assert(instance->buffer_size == 0);
    471         assert(instance->packet == NULL);
    472 
    473         instance->packet_size = instance->max_packet_size;
    474         instance->next_step = tracker_call_in_and_dispose;
    475 
    476         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    477             instance->packet_size, 1, false, instance->target, USB_PID_IN,
    478             instance->packet);
    479 
    480         tracker_schedule(instance);
    481 }
    482 
    483 void tracker_control_read_status_old(tracker_t *instance)
    484 {
    485         assert(instance);
    486         assert(instance->max_packet_size == 0);
    487         assert(instance->buffer_size == 0);
    488         assert(instance->packet == NULL);
    489 
    490         instance->packet_size = instance->max_packet_size;
    491         instance->next_step = tracker_call_out_and_dispose;
    492 
    493         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    494             instance->packet_size, 1, false, instance->target, USB_PID_OUT,
    495             instance->packet);
    496 
    497375        tracker_schedule(instance);
    498376}
  • uspace/drv/uhci-hcd/tracker.h

    rf6309b6 r7dd3318  
    4141
    4242#include "uhci_struct/transfer_descriptor.h"
     43#include "uhci_struct/queue_head.h"
    4344
    4445typedef enum {
     
    4748} dev_speed_t;
    4849
    49 struct transfer_list;
    50 
    5150typedef struct tracker
    5251{
    5352        link_t link;
     53        dev_speed_t speed;
    5454        usb_target_t target;
    5555        usb_transfer_type_t transfer_type;
     
    5959        };
    6060        void *arg;
     61        char *transport_buffer;
     62        char *setup_buffer;
     63        size_t setup_size;
    6164        char *buffer;
    62         char *packet;
    6365        size_t buffer_size;
    6466        size_t max_packet_size;
    65         size_t packet_size;
    66         size_t buffer_offset;
    67         dev_speed_t speed;
     67        size_t packets;
     68        size_t transfered_size;
     69        int error;
    6870        device_t *dev;
    69         transfer_descriptor_t *td;
     71        queue_head_t *qh;
     72        transfer_descriptor_t *tds;
    7073        void (*next_step)(struct tracker*);
    71         unsigned toggle:1;
    72 
    73         struct transfer_list *scheduled_list;
    7474} tracker_t;
    75 
    7675
    7776tracker_t * tracker_get(device_t *dev, usb_target_t target,
    7877    usb_transfer_type_t transfer_type, size_t max_packet_size,
    7978    dev_speed_t speed, char *buffer, size_t size,
     79                char *setup_buffer, size_t setup_size,
    8080    usbhc_iface_transfer_in_callback_t func_in,
    8181    usbhc_iface_transfer_out_callback_t func_out, void *arg);
    8282
    83 void tracker_control_write(
    84     tracker_t *instance, char* setup_buffer, size_t setup_size);
     83bool tracker_is_complete(tracker_t *instance);
    8584
    86 void tracker_control_read(
    87     tracker_t *instance, char* setup_buffer, size_t setup_size);
     85void tracker_control_write(tracker_t *instance);
     86
     87void tracker_control_read(tracker_t *instance);
    8888
    8989void tracker_interrupt_in(tracker_t *instance);
  • uspace/drv/uhci-hcd/transfer_list.c

    rf6309b6 r7dd3318  
    5151
    5252        queue_head_init(instance->queue_head);
     53        list_initialize(&instance->tracker_list);
    5354        return EOK;
    5455}
     
    5859        assert(instance);
    5960        assert(next);
    60         instance->next = next;
    6161        if (!instance->queue_head)
    6262                return;
    63         queue_head_add_next(instance->queue_head, next->queue_head_pa);
     63        queue_head_append_qh(instance->queue_head, next->queue_head_pa);
    6464}
    6565/*----------------------------------------------------------------------------*/
     
    6969        assert(tracker);
    7070
    71         uint32_t pa = (uintptr_t)addr_to_phys(tracker->td);
     71        uint32_t pa = (uintptr_t)addr_to_phys(tracker->qh);
    7272        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
     73        pa |= LINK_POINTER_QUEUE_HEAD_FLAG;
    7374
    7475
    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);
     76        if ((instance->queue_head->element & LINK_POINTER_TERMINATE_FLAG) != 0) {
    7877                /* there is nothing scheduled */
    79                 instance->last_tracker = tracker;
     78                list_append(&tracker->link, &instance->tracker_list);
    8079                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);
     80                usb_log_debug2("Added tracker(%p) to queue %s first.\n",
     81                        tracker, instance->name);
    8382                return;
    8483        }
    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;
    91 
    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 */
    96         if (instance->queue_head->element & LINK_POINTER_TERMINATE_FLAG) {
    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);
    100         }
     84        /* now we can be sure that there is someting scheduled */
     85        assert(!list_empty(&instance->tracker_list));
     86        tracker_t *first = list_get_instance(
     87                  instance->tracker_list.next, tracker_t, link);
     88        tracker_t *last = list_get_instance(
     89            instance->tracker_list.prev, tracker_t, link);
     90        queue_head_append_qh(last->qh, pa);
     91        list_append(&tracker->link, &instance->tracker_list);
     92        usb_log_debug2("Added tracker(%p) to queue %s last, first is %p.\n",
     93                tracker, instance->name, first );
    10194}
    10295/*----------------------------------------------------------------------------*/
    103 void transfer_list_remove_tracker(transfer_list_t *instance, tracker_t *tracker)
     96static void transfer_list_remove_tracker(
     97    transfer_list_t *instance, tracker_t *tracker)
    10498{
    10599        assert(instance);
    106100        assert(tracker);
    107101        assert(instance->queue_head);
    108         assert(tracker->td);
     102        assert(tracker->qh);
    109103
    110         uint32_t pa = (uintptr_t)addr_to_phys(tracker->td);
    111         if ((instance->queue_head->element & LINK_POINTER_ADDRESS_MASK) == pa) {
    112                 instance->queue_head->element = tracker->td->next;
     104        /* I'm the first one here */
     105        if (tracker->link.next == &instance->tracker_list) {
     106                usb_log_debug("Removing tracer %p was first, next element %x.\n",
     107                        tracker, tracker->qh->next_queue);
     108                instance->queue_head->element = tracker->qh->next_queue;
     109        } else {
     110                usb_log_debug("Removing tracer %p was NOT first, next element %x.\n",
     111                        tracker, tracker->qh->next_queue);
     112                tracker_t *prev = list_get_instance(tracker->link.prev, tracker_t, link);
     113                prev->qh->next_queue = tracker->qh->next_queue;
     114        }
     115        list_remove(&tracker->link);
     116}
     117/*----------------------------------------------------------------------------*/
     118void transfer_list_check(transfer_list_t *instance)
     119{
     120        assert(instance);
     121        link_t *current = instance->tracker_list.next;
     122        while (current != &instance->tracker_list) {
     123                link_t *next = current->next;
     124                tracker_t *tracker = list_get_instance(current, tracker_t, link);
     125
     126                if (tracker_is_complete(tracker)) {
     127                        transfer_list_remove_tracker(instance, tracker);
     128                        tracker->next_step(tracker);
     129                }
     130                current = next;
    113131        }
    114132}
  • uspace/drv/uhci-hcd/transfer_list.h

    rf6309b6 r7dd3318  
    4141typedef struct transfer_list
    4242{
    43         tracker_t *last_tracker;
    44 
    4543        queue_head_t *queue_head;
    4644        uint32_t queue_head_pa;
    4745        struct transfer_list *next;
    4846        const char *name;
     47        link_t tracker_list;
    4948} transfer_list_t;
    5049
     
    5958        queue_head_dispose(instance->queue_head);
    6059}
     60void transfer_list_check(transfer_list_t *instance);
    6161
    6262void transfer_list_add_tracker(transfer_list_t *instance, tracker_t *tracker);
    63 
    64 void transfer_list_remove_tracker(transfer_list_t *instance, tracker_t *track);
    65 
    6663#endif
    6764/**
  • uspace/drv/uhci-hcd/uhci.c

    rf6309b6 r7dd3318  
    158158        const int low_speed = (tracker->speed == LOW_SPEED);
    159159        if (!allowed_usb_packet(
    160             low_speed, tracker->transfer_type, tracker->packet_size)) {
     160            low_speed, tracker->transfer_type, tracker->max_packet_size)) {
    161161                usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n",
    162162                          low_speed ? "LOW" : "FULL" , tracker->transfer_type,
    163                     tracker->packet_size);
     163                    tracker->max_packet_size);
    164164                return ENOTSUP;
    165165        }
    166166        /* 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());
    173167
    174168        transfer_list_t *list =
     
    176170        assert(list);
    177171        transfer_list_add_tracker(list, tracker);
    178         list_append(&tracker->link, &instance->tracker_list);
    179 
    180         tracker->scheduled_list = list;
    181 
    182         usb_log_debug2("Scheduler(%d) releasing tracker list mutex.\n",
    183             fibril_get_id());
    184         fibril_mutex_unlock(&instance->tracker_list_mutex);
    185         usb_log_debug2("Scheduler(%d) released tracker list mutex.\n",
    186             fibril_get_id());
    187172
    188173        return EOK;
     
    196181
    197182        while(1) {
    198                 LIST_INITIALIZE(done_trackers);
    199                 /* tracker iteration */
    200 
    201                 usb_log_debug2("Cleaner(%d) acquiring tracker list mutex.\n",
    202                     fibril_get_id());
    203                 fibril_mutex_lock(&instance->tracker_list_mutex);
    204                 usb_log_debug2("Cleaner(%d) acquired tracker list mutex.\n",
    205                     fibril_get_id());
    206 
    207                 link_t *current = instance->tracker_list.next;
    208                 while (current != &instance->tracker_list)
    209                 {
    210 
    211                         link_t *next = current->next;
    212                         tracker_t *tracker = list_get_instance(current, tracker_t, link);
    213 
    214                         assert(current == &tracker->link);
    215                         assert(tracker);
    216                         assert(tracker->next_step);
    217                         assert(tracker->td);
    218 
    219                         if (!transfer_descriptor_is_active(tracker->td)) {
    220                                 usb_log_info("Found inactive tracker with status: %x:%x.\n",
    221                                     tracker->td->status, tracker->td->device);
    222                                 list_remove(current);
    223                                 list_append(current, &done_trackers);
    224                         }
    225                         current = next;
    226                 }
    227 
    228                 usb_log_debug2("Cleaner(%d) releasing tracker list mutex.\n",
    229                     fibril_get_id());
    230                 fibril_mutex_unlock(&instance->tracker_list_mutex);
    231                 usb_log_debug2("Cleaner(%d) released tracker list mutex.\n",
    232                     fibril_get_id());
    233 
    234                 while (!list_empty(&done_trackers)) {
    235                         tracker_t *tracker = list_get_instance(
    236                           done_trackers.next, tracker_t, link);
    237                         list_remove(&tracker->link);
    238                         tracker->next_step(tracker);
    239                 }
     183                transfer_list_check(&instance->transfers_interrupt);
     184                transfer_list_check(&instance->transfers_control_slow);
     185                transfer_list_check(&instance->transfers_control_full);
     186                transfer_list_check(&instance->transfers_bulk_full);
    240187                async_usleep(UHCI_CLEANER_TIMEOUT);
    241188        }
  • uspace/drv/uhci-hcd/uhci.h

    rf6309b6 r7dd3318  
    7272
    7373#define UHCI_FRAME_LIST_COUNT 1024
    74 #define UHCI_CLEANER_TIMEOUT 1000
     74#define UHCI_CLEANER_TIMEOUT 1000000
    7575#define UHCI_DEBUGER_TIMEOUT 5000000
    7676
  • uspace/drv/uhci-hcd/uhci_struct/queue_head.h

    rf6309b6 r7dd3318  
    5555}
    5656
    57 static inline void queue_head_add_next(queue_head_t *instance, uint32_t next_queue_pa)
     57static inline void queue_head_append_qh(queue_head_t *instance, uint32_t pa)
    5858{
    59         if (next_queue_pa) {
    60                 instance->next_queue = (next_queue_pa & LINK_POINTER_ADDRESS_MASK)
    61                   | LINK_POINTER_QUEUE_HEAD_FLAG;
     59        if (pa) {
     60                instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
     61                    | LINK_POINTER_QUEUE_HEAD_FLAG;
    6262        }
    6363}
    6464
    65 static inline queue_head_t * queue_head_get()
    66         { return malloc32(sizeof(queue_head_t)); }
     65static inline void queue_head_element_qh(queue_head_t *instance, uint32_t pa)
     66{
     67        if (pa) {
     68                instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK)
     69                    | LINK_POINTER_QUEUE_HEAD_FLAG;
     70        }
     71}
     72
     73static inline void queue_head_element_td(queue_head_t *instance, uint32_t pa)
     74{
     75        if (pa) {
     76                instance->element = (pa & LINK_POINTER_ADDRESS_MASK);
     77        }
     78}
     79
     80static inline queue_head_t * queue_head_get() {
     81        queue_head_t *ret = malloc32(sizeof(queue_head_t));
     82        if (ret)
     83                queue_head_init(ret);
     84        return ret;
     85}
    6786
    6887static inline void queue_head_dispose(queue_head_t *head)
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c

    rf6309b6 r7dd3318  
    4040void transfer_descriptor_init(transfer_descriptor_t *instance,
    4141    int error_count, size_t size, bool toggle, bool isochronous,
    42     usb_target_t target, int pid, void *buffer)
     42    usb_target_t target, int pid, void *buffer, transfer_descriptor_t *next)
    4343{
    4444        assert(instance);
    4545
    46         instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
     46        instance->next =
     47            (next != NULL) ? addr_to_phys(next) : LINK_POINTER_TERMINATE_FLAG;
    4748
    4849        instance->status = 0
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h

    rf6309b6 r7dd3318  
    9393void transfer_descriptor_init(transfer_descriptor_t *instance,
    9494    int error_count, size_t size, bool toggle, bool isochronous,
    95     usb_target_t target, int pid, void *buffer);
     95    usb_target_t target, int pid, void *buffer, transfer_descriptor_t * next);
    9696
    9797int transfer_descriptor_status(transfer_descriptor_t *instance);
     98
     99static inline size_t transfer_descriptor_actual_size(
     100    transfer_descriptor_t *instance)
     101{
     102        assert(instance);
     103        return
     104            ((instance->status >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
     105}
    98106
    99107static inline bool transfer_descriptor_is_active(
  • uspace/drv/uhci-hcd/utils/malloc32.h

    rf6309b6 r7dd3318  
    4545#define UHCI_REQUIRED_PAGE_SIZE 4096
    4646
    47 static inline void * addr_to_phys(void *addr)
     47static inline uintptr_t addr_to_phys(void *addr)
    4848{
    4949        uintptr_t result;
     
    5151
    5252        assert(ret == 0);
    53         return (void*)(result | ((uintptr_t)addr & 0xfff));
     53        return (result | ((uintptr_t)addr & 0xfff));
    5454}
    5555
Note: See TracChangeset for help on using the changeset viewer.