Changeset 9a818a9 in mainline


Ignore:
Timestamp:
2011-02-07T12:49:19Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e2172cf8
Parents:
da17cf0
Message:

Adds support for tracker scheduling and callback

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

Legend:

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

    rda17cf0 r9a818a9  
    3333 */
    3434#include <errno.h>
    35 #include <mem.h>
    3635
    3736#include <usb/debug.h>
    3837
    3938#include "tracker.h"
     39#include "uhci.h"
     40#include "utils/malloc32.h"
    4041
    4142#define SETUP_PACKET_DATA_SIZE 8
     
    4445#define MIN(a,b) ((a < b) ? a : b)
    4546
     47static int tracker_schedule(tracker_t *instance);
     48
    4649static void tracker_control_read_data(tracker_t *instance);
    4750static void tracker_control_write_data(tracker_t *instance);
    4851static void tracker_control_read_status(tracker_t *instance);
    4952static void tracker_control_write_status(tracker_t *instance);
    50 
    51 
    52 int tracker_init(tracker_t *instance, device_t *dev, usb_target_t target,
    53     size_t max_packet_size, dev_speed_t speed, char *buffer, size_t size,
     53static void tracker_call_in(tracker_t *instance);
     54static void tracker_call_out(tracker_t *instance);
     55static void tracker_call_in_and_dispose(tracker_t *instance);
     56static void tracker_call_out_and_dispose(tracker_t *instance);
     57
     58
     59tracker_t * tracker_get(device_t *dev, usb_target_t target,
     60    usb_transfer_type_t transfer_type, size_t max_packet_size,
     61    dev_speed_t speed, char *buffer, size_t size,
    5462    usbhc_iface_transfer_in_callback_t func_in,
    5563    usbhc_iface_transfer_out_callback_t func_out, void *arg)
    5664{
    57         assert(instance);
    5865        assert(func_in == NULL || func_out == NULL);
    5966        assert(func_in != NULL || func_out != NULL);
     67
     68        tracker_t *instance = malloc(sizeof(tracker_t));
     69        if (!instance) {
     70                usb_log_error("Failed to allocate tracker isntance.\n");
     71                return NULL;
     72        }
    6073
    6174        instance->td = malloc32(sizeof(transfer_descriptor_t));
    6275        if (!instance->td) {
    6376                usb_log_error("Failed to allocate transfer descriptor.\n");
    64                 return ENOMEM;
     77                free(instance);
     78                return NULL;
    6579        }
    6680
     
    6983                usb_log_error("Failed to allocate device acessible buffer.\n");
    7084                free32(instance->td);
    71                 return ENOMEM;
     85                free(instance);
     86                return NULL;
    7287        }
    7388        instance->max_packet_size = max_packet_size;
     
    7792        link_initialize(&instance->link);
    7893        instance->target = target;
     94        instance->transfer_type = transfer_type;
    7995
    8096        if (func_out)
     
    87103        instance->arg = arg;
    88104        instance->toggle = 0;
    89         return EOK;
     105
     106        return instance;
    90107}
    91108/*----------------------------------------------------------------------------*/
     
    94111        assert(instance);
    95112        assert(instance->buffer_offset == 0);
     113
    96114        instance->packet_size = SETUP_PACKET_DATA_SIZE;
    97115        memcpy(instance->packet, instance->buffer, SETUP_PACKET_DATA_SIZE);
     116
    98117        transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    99118            SETUP_PACKET_DATA_SIZE, false, instance->target, USB_PID_SETUP,
    100119            instance->packet);
     120
    101121        instance->buffer_offset += SETUP_PACKET_DATA_SIZE;
    102122        instance->next_step = tracker_control_write_data;
    103         //TODO: add to scheduler
     123
     124        tracker_schedule(instance);
    104125}
    105126/*----------------------------------------------------------------------------*/
     
    108129        assert(instance);
    109130        assert(instance->buffer_offset == 0);
     131
    110132        instance->packet_size = SETUP_PACKET_DATA_SIZE;
    111133        memcpy(instance->packet, instance->buffer, SETUP_PACKET_DATA_SIZE);
     134
    112135        transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    113136            SETUP_PACKET_DATA_SIZE, false, instance->target, USB_PID_SETUP,
    114137            instance->packet);
     138
    115139        instance->buffer_offset += SETUP_PACKET_DATA_SIZE;
    116140        instance->next_step = tracker_control_read_data;
    117         //TODO: add to scheduler
     141
     142        tracker_schedule(instance);
    118143}
    119144/*----------------------------------------------------------------------------*/
     
    136161        /* prepare next packet, no copy, we are receiving data */
    137162        instance->packet_size = MIN(instance->max_packet_size,
    138                         instance->buffer_size - instance->buffer_offset);
    139         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    140                         instance->packet_size, false, instance->target, USB_PID_IN,
    141                         instance->packet);
    142         // TODO: add to uhci scheduler
     163            instance->buffer_size - instance->buffer_offset);
     164
     165        transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
     166            instance->packet_size, false, instance->target, USB_PID_IN,
     167            instance->packet);
     168
     169        tracker_schedule(instance);
    143170
    144171        /* set next step */
     
    166193        /* prepare next packet, copy data to packet */
    167194        instance->packet_size = MIN(instance->max_packet_size,
    168                         instance->buffer_size - instance->buffer_offset);
     195            instance->buffer_size - instance->buffer_offset);
    169196        memcpy(instance->packet, instance->buffer + instance->buffer_offset,
    170197            instance->packet_size);
    171198        transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    172                         instance->packet_size, false, instance->target, USB_PID_OUT,
    173                         instance->packet);
    174         // TODO: add to uhci scheduler
     199            instance->packet_size, false, instance->target, USB_PID_OUT,
     200            instance->packet);
     201
     202        tracker_schedule(instance);
    175203
    176204        /* set next step */
     
    202230        instance->packet_size = 0;
    203231        transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    204                         0, false, instance->target, USB_PID_OUT, NULL);
    205         // TODO: add to uhci scheduler
     232            0, false, instance->target, USB_PID_OUT, NULL);
     233
     234        tracker_schedule(instance);
    206235
    207236        /* set next step, callback and cleanup */
     
    229258        instance->packet_size = 0;
    230259        transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    231                         0, false, instance->target, USB_PID_OUT, NULL);
    232         // TODO: add to uhci scheduler
     260            0, false, instance->target, USB_PID_OUT, NULL);
     261
     262        tracker_schedule(instance);
    233263
    234264        /* set next step, callback and cleanup */
     
    288318        free(instance);
    289319}
     320/*----------------------------------------------------------------------------*/
     321int tracker_schedule(tracker_t *instance)
     322{
     323        assert(instance);
     324        uhci_t *hc = dev_to_uhci(instance->dev);
     325        assert(hc);
     326        return uhci_schedule(hc, instance);
     327}
     328/*----------------------------------------------------------------------------*/
    290329/* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
    291330void tracker_control_setup_old(tracker_t *instance)
     
    293332        assert(instance);
    294333        assert(instance->buffer_offset == 0);
     334
    295335        instance->packet_size = SETUP_PACKET_DATA_SIZE;
    296336        memcpy(instance->packet, instance->buffer, SETUP_PACKET_DATA_SIZE);
     337
    297338        transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    298339            SETUP_PACKET_DATA_SIZE, false, instance->target, USB_PID_SETUP,
    299340            instance->packet);
     341
    300342        instance->buffer_offset += SETUP_PACKET_DATA_SIZE;
    301343        instance->next_step = tracker_call_out_and_dispose;
    302         //TODO: add to scheduler
     344
     345        tracker_schedule(instance);
    303346}
    304347
     
    307350        assert(instance);
    308351        assert(instance->max_packet_size == instance->buffer_size);
     352
    309353        memcpy(instance->packet, instance->buffer, instance->max_packet_size);
    310354        instance->packet_size = instance->max_packet_size;
    311         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    312                         instance->packet_size, false, instance->target, USB_PID_OUT,
    313                         instance->packet);
     355
     356        transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
     357            instance->packet_size, false, instance->target, USB_PID_OUT,
     358            instance->packet);
    314359        instance->next_step = tracker_call_out_and_dispose;
     360
     361        tracker_schedule(instance);
    315362}
    316363
     
    319366        assert(instance);
    320367        assert(instance->max_packet_size == instance->buffer_size);
     368
    321369        instance->packet_size = instance->max_packet_size;
    322         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    323                         instance->packet_size, false, instance->target, USB_PID_IN,
    324                         instance->packet);
     370
     371        transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
     372            instance->packet_size, false, instance->target, USB_PID_IN,
     373            instance->packet);
     374
    325375        instance->next_step = tracker_call_in_and_dispose;
     376
     377        tracker_schedule(instance);
    326378}
    327379
     
    334386
    335387        instance->packet_size = instance->max_packet_size;
    336         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    337                         instance->packet_size, false, instance->target, USB_PID_IN,
    338                         instance->packet);
    339388        instance->next_step = tracker_call_in_and_dispose;
     389
     390        transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
     391            instance->packet_size, false, instance->target, USB_PID_IN,
     392            instance->packet);
     393
     394        tracker_schedule(instance);
    340395}
    341396
     
    348403
    349404        instance->packet_size = instance->max_packet_size;
    350         transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
    351                         instance->packet_size, false, instance->target, USB_PID_OUT,
    352                         instance->packet);
    353405        instance->next_step = tracker_call_out_and_dispose;
     406
     407        transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
     408            instance->packet_size, false, instance->target, USB_PID_OUT,
     409            instance->packet);
     410
     411        tracker_schedule(instance);
    354412}
    355413/**
  • uspace/drv/uhci-hcd/tracker.h

    rda17cf0 r9a818a9  
    5151        link_t link;
    5252        usb_target_t target;
     53        usb_transfer_type_t transfer_type;
    5354        union {
    5455                usbhc_iface_transfer_in_callback_t callback_in;
     
    7071
    7172
    72 int tracker_init(tracker_t *instance, device_t *dev, usb_target_t target,
    73     size_t packet_size, dev_speed_t speed, char *buffer, size_t size,
     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,
    7476    usbhc_iface_transfer_in_callback_t func_in,
    7577    usbhc_iface_transfer_out_callback_t func_out, void *arg);
     
    8284
    8385void tracker_interrupt_out(tracker_t *instance);
    84 
    85 void tracker_call_in(tracker_t *instance);
    86 
    87 void tracker_call_out(tracker_t *instance);
    88 
    89 void tracker_call_in_and_dispose(tracker_t *instance);
    90 
    91 void tracker_call_out_and_dispose(tracker_t *instance);
    9286
    9387/* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
  • uspace/drv/uhci-hcd/transfer_list.c

    rda17cf0 r9a818a9  
    9696        return EOK;
    9797}
     98/*----------------------------------------------------------------------------*/
     99void transfer_list_add_tracker(transfer_list_t *instance, tracker_t *tracker)
     100{
     101        assert(instance);
     102        assert(tracker);
     103
     104        uint32_t pa = (uintptr_t)addr_to_phys(tracker->td);
     105        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
     106
     107        if (instance->queue_head->element & LINK_POINTER_TERMINATE_FLAG) {
     108                /* there is nothing scheduled */
     109                instance->last_tracker = tracker;
     110                instance->queue_head->element = pa;
     111                return;
     112        }
     113        /* now we can be sure that last_tracker is a valid pointer */
     114        instance->last_tracker->td->next = pa;
     115        instance->last_tracker = tracker;
     116
     117        /* check again, may be use atomic compare and swap */
     118        if (instance->queue_head->element & LINK_POINTER_TERMINATE_FLAG) {
     119                instance->queue_head->element = pa;
     120        }
     121}
    98122/**
    99123 * @}
  • uspace/drv/uhci-hcd/transfer_list.h

    rda17cf0 r9a818a9  
    3737#include "uhci_struct/queue_head.h"
    3838#include "uhci_struct/transfer_descriptor.h"
     39#include "tracker.h"
    3940
    4041typedef struct transfer_list
     
    4243        transfer_descriptor_t *first;
    4344        transfer_descriptor_t *last;
     45
     46        tracker_t *last_tracker;
     47
    4448        queue_head_t *queue_head;
    4549        uint32_t queue_head_pa;
     
    6165  transfer_list_t *instance, transfer_descriptor_t *transfer);
    6266
     67void transfer_list_add_tracker(transfer_list_t *instance, tracker_t *tracker);
     68
    6369#endif
    6470/**
  • uspace/drv/uhci-hcd/uhci.c

    rda17cf0 r9a818a9  
    8686
    8787        const uintptr_t pa = (uintptr_t)addr_to_phys(instance->frame_list);
    88 
    8988        pio_write_32(&instance->registers->flbaseadd, (uint32_t)pa);
     89
     90        list_initialize(&instance->tracker_list);
    9091
    9192        instance->cleaner = fibril_create(uhci_clean_finished, instance);
     
    209210        return EOK;
    210211}
    211 /*---------------------------------------------------------------------------*/
     212/*----------------------------------------------------------------------------*/
     213int uhci_schedule(uhci_t *instance, tracker_t *tracker)
     214{
     215        assert(instance);
     216        assert(tracker);
     217        const int low_speed = (tracker->speed == LOW_SPEED);
     218        if (!allowed_usb_packet(
     219            low_speed, tracker->transfer_type, tracker->packet_size)) {
     220                usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n",
     221                          low_speed ? "LOW" : "FULL" , tracker->transfer_type,
     222                    tracker->packet_size);
     223                return ENOTSUP;
     224        }
     225        /* TODO: check available bandwith here */
     226
     227        transfer_list_t *list =
     228            instance->transfers[low_speed][tracker->transfer_type];
     229        assert(list);
     230        transfer_list_add_tracker(list, tracker);
     231        list_append(&tracker->link, &instance->tracker_list);
     232
     233        return EOK;
     234}
     235/*----------------------------------------------------------------------------*/
    212236int uhci_clean_finished(void* arg)
    213237{
     
    217241
    218242        while(1) {
    219                 usb_log_debug("Running cleaning fibril on: %p.\n", instance);
     243                /* tracker iteration */
     244                link_t *current = instance->tracker_list.next;
     245                while (current != &instance->tracker_list)
     246                {
     247                        link_t *next = current->next;
     248                        tracker_t *tracker = list_get_instance(current, tracker_t, link);
     249                        assert(current == &tracker->link);
     250                        if (!transfer_descriptor_is_active(tracker->td)) {
     251                                usb_log_debug("Found inactive tracker.\n");
     252                                list_remove(current);
     253                                tracker->next_step(tracker);
     254                        }
     255                        current = next;
     256                }
    220257                /* iterate all transfer queues */
    221258                transfer_list_t *current_list = &instance->transfers_interrupt;
  • uspace/drv/uhci-hcd/uhci.h

    rda17cf0 r9a818a9  
    3737
    3838#include <fibril.h>
     39#include <adt/list.h>
    3940
    4041#include <usb/addrkeep.h>
     
    4243
    4344#include "transfer_list.h"
     45#include "tracker.h"
    4446
    4547typedef struct uhci_regs {
     
    7981        link_pointer_t *frame_list;
    8082
     83        link_t tracker_list;
     84
    8185        transfer_list_t transfers_bulk_full;
    8286        transfer_list_t transfers_control_full;
     
    108112  void *arg );
    109113
     114int uhci_schedule(uhci_t *instance, tracker_t *tracker);
     115
    110116static inline uhci_t * dev_to_uhci(device_t *dev)
    111117        { return (uhci_t*)dev->driver_data; }
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h

    rda17cf0 r9a818a9  
    124124int transfer_descriptor_status(transfer_descriptor_t *instance);
    125125
     126static inline bool transfer_descriptor_is_active(
     127    transfer_descriptor_t *instance)
     128{
     129        assert(instance);
     130        return instance->status & TD_STATUS_ERROR_ACTIVE;
     131}
     132
    126133static inline void transfer_descriptor_append(
    127134  transfer_descriptor_t *instance, transfer_descriptor_t *item)
Note: See TracChangeset for help on using the changeset viewer.