Changeset 881c47b in mainline


Ignore:
Timestamp:
2011-02-04T14:45:42Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
dcef3669
Parents:
97e87de
Message:

New UHCI packet scheduler

queues are named for nicer debug output
slow_speed is set by iface functions

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

Legend:

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

    r97e87de r881c47b  
    110110        assert(hc);
    111111        return uhci_transfer(hc, dev, target, USB_TRANSFER_INTERRUPT, 0, USB_PID_OUT,
    112                 data, size, callback, NULL, arg);
     112                false, data, size, callback, NULL, arg);
    113113}
    114114/*----------------------------------------------------------------------------*/
     
    121121        assert(hc);
    122122        return uhci_transfer(hc, dev, target, USB_TRANSFER_INTERRUPT, 0, USB_PID_IN,
    123                 data, size, NULL, callback, arg);
     123                false, data, size, NULL, callback, arg);
    124124}
    125125/*----------------------------------------------------------------------------*/
     
    132132        assert(hc);
    133133        return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_SETUP,
    134                 data, size, callback, NULL, arg);
     134                false, data, size, callback, NULL, arg);
    135135}
    136136/*----------------------------------------------------------------------------*/
     
    143143        assert(hc);
    144144        return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 1, USB_PID_OUT,
    145                 data, size, callback, NULL, arg);
     145                false, data, size, callback, NULL, arg);
    146146}
    147147/*----------------------------------------------------------------------------*/
     
    153153        assert(hc);
    154154        return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_IN,
    155                 NULL, 0, NULL, callback, arg);
     155                false, NULL, 0, NULL, callback, arg);
    156156}
    157157/*----------------------------------------------------------------------------*/
     
    164164        assert(hc);
    165165        return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_SETUP,
    166                 data, size, callback, NULL, arg);
     166                false, data, size, callback, NULL, arg);
    167167}
    168168/*----------------------------------------------------------------------------*/
     
    175175        assert(hc);
    176176        return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 1, USB_PID_IN,
    177                 data, size, NULL, callback, arg);
     177                false, data, size, NULL, callback, arg);
    178178}
    179179/*----------------------------------------------------------------------------*/
     
    185185        assert(hc);
    186186        return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_OUT,
    187                 NULL, 0, callback, NULL, arg);
     187                false, NULL, 0, callback, NULL, arg);
    188188}
    189189
  • uspace/drv/uhci-hcd/transfer_list.c

    r97e87de r881c47b  
    3838#include "transfer_list.h"
    3939
    40 int transfer_list_init(transfer_list_t *instance, transfer_list_t *next)
     40int transfer_list_init(transfer_list_t *instance, const char *name)
    4141{
    4242        assert(instance);
    4343        instance->first = NULL;
    4444        instance->last = NULL;
     45        instance->next = NULL;
     46        instance->name = name;
    4547        instance->queue_head = queue_head_get();
    4648        if (!instance->queue_head) {
     
    5052        instance->queue_head_pa = (uintptr_t)addr_to_phys(instance->queue_head);
    5153
    52         uint32_t next_pa = next ? next->queue_head_pa : 0;
    53         queue_head_init(instance->queue_head, next_pa);
     54        queue_head_init(instance->queue_head);
    5455        return EOK;
     56}
     57/*----------------------------------------------------------------------------*/
     58void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
     59{
     60        assert(instance);
     61        assert(next);
     62        instance->next = next;
     63        if (!instance->queue_head)
     64                return;
     65        queue_head_add_next(instance->queue_head, next->queue_head_pa);
    5566}
    5667/*----------------------------------------------------------------------------*/
     
    8192                instance->queue_head->element = (pa & LINK_POINTER_ADDRESS_MASK);
    8293        }
    83         usb_log_debug("Successfully added transfer to the hc queue %p.\n",
    84           instance);
     94        usb_log_debug("Successfully added transfer to the hc queue %S.\n",
     95          instance->name);
    8596        return EOK;
    8697}
  • uspace/drv/uhci-hcd/transfer_list.h

    r97e87de r881c47b  
    4444        queue_head_t *queue_head;
    4545        uint32_t queue_head_pa;
     46        struct transfer_list *next;
     47        const char *name;
    4648} transfer_list_t;
    4749
    48 int transfer_list_init(transfer_list_t *instance, transfer_list_t *next);
     50int transfer_list_init(transfer_list_t *instance, const char *name);
     51
     52void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
    4953
    5054static inline void transfer_list_fini(transfer_list_t *instance)
  • uspace/drv/uhci-hcd/uhci.c

    r97e87de r881c47b  
    3939#include "uhci.h"
    4040
    41 static int uhci_init_transfer_lists(transfer_list_t list[]);
     41static int uhci_init_transfer_lists(uhci_t *instance);
    4242static int uhci_clean_finished(void *arg);
    4343static int uhci_debug_checker(void *arg);
     
    6464
    6565        /* init transfer lists */
    66         ret = uhci_init_transfer_lists(instance->transfers);
     66        ret = uhci_init_transfer_lists(instance);
    6767        CHECK_RET_RETURN("Failed to initialize transfer lists.\n");
    6868        usb_log_debug("Transfer lists initialized.\n");
     
    7676        /* initialize all frames to point to the first queue head */
    7777        const uint32_t queue =
    78           instance->transfers[USB_TRANSFER_INTERRUPT].queue_head_pa
     78          instance->transfers_interrupt.queue_head_pa
    7979          | LINK_POINTER_QUEUE_HEAD_FLAG;
    8080        unsigned i = 0;
     
    9797            UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET);
    9898        usb_log_debug("Started UHCI HC.\n");
    99 /*
     99
    100100        uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
    101101        cmd |= UHCI_CMD_DEBUG;
    102102        pio_write_16(&instance->registers->usbcmd, cmd);
    103 */
     103
    104104        return EOK;
    105105}
    106106/*----------------------------------------------------------------------------*/
    107 int uhci_init_transfer_lists(transfer_list_t transfers[])
    108 {
    109         //TODO:refactor
    110         transfers[USB_TRANSFER_ISOCHRONOUS].first = NULL;
    111         transfers[USB_TRANSFER_ISOCHRONOUS].last = NULL;
    112 
     107int uhci_init_transfer_lists(uhci_t *instance)
     108{
     109        assert(instance);
     110
     111        /* initialize */
    113112        int ret;
    114         ret = transfer_list_init(&transfers[USB_TRANSFER_BULK], NULL);
    115         if (ret != EOK) {
    116                 usb_log_error("Failed to initialize bulk queue.\n");
    117                 return ret;
    118         }
    119 
    120         ret = transfer_list_init(
    121           &transfers[USB_TRANSFER_CONTROL], &transfers[USB_TRANSFER_BULK]);
    122         if (ret != EOK) {
    123                 usb_log_error("Failed to initialize control queue.\n");
    124                 transfer_list_fini(&transfers[USB_TRANSFER_BULK]);
    125                 return ret;
    126         }
    127 
    128         ret = transfer_list_init(
    129           &transfers[USB_TRANSFER_INTERRUPT], &transfers[USB_TRANSFER_CONTROL]);
    130         if (ret != EOK) {
    131                 usb_log_error("Failed to initialize interrupt queue.\n");
    132                 transfer_list_fini(&transfers[USB_TRANSFER_CONTROL]);
    133                 transfer_list_fini(&transfers[USB_TRANSFER_BULK]);
    134                 return ret;
    135         }
     113        ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
     114        assert(ret == EOK);
     115        ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL");
     116        assert(ret == EOK);
     117        ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW");
     118        assert(ret == EOK);
     119        ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
     120        assert(ret == EOK);
     121
     122        transfer_list_set_next(&instance->transfers_control_full,
     123                &instance->transfers_bulk_full);
     124        transfer_list_set_next(&instance->transfers_control_slow,
     125                &instance->transfers_control_full);
     126        transfer_list_set_next(&instance->transfers_interrupt,
     127                &instance->transfers_control_slow);
     128
     129        /*FSBR*/
     130#ifdef FSBR
     131        transfer_list_set_next(&instance->transfers_bulk_full,
     132                &instance->transfers_control_full);
     133#endif
     134
     135        instance->transfers[0][USB_TRANSFER_INTERRUPT] =
     136          &instance->transfers_interrupt;
     137        instance->transfers[1][USB_TRANSFER_INTERRUPT] =
     138          &instance->transfers_interrupt;
     139        instance->transfers[0][USB_TRANSFER_CONTROL] =
     140          &instance->transfers_control_full;
     141        instance->transfers[1][USB_TRANSFER_CONTROL] =
     142          &instance->transfers_control_slow;
     143        instance->transfers[0][USB_TRANSFER_CONTROL] =
     144          &instance->transfers_control_full;
    136145
    137146        return EOK;
     
    145154        bool toggle,
    146155  usb_packet_id pid,
     156        bool low_speed,
    147157  void *buffer, size_t size,
    148158  usbhc_iface_transfer_out_callback_t callback_out,
     
    165175        if (size >= 1024) {
    166176                usb_log_warning("Transfer too big.\n");
     177                return ENOTSUP;
     178        }
     179        transfer_list_t *list = instance->transfers[low_speed][transfer_type];
     180        if (!list) {
     181                usb_log_warning("UNSUPPORTED transfer %d-%d.\n", low_speed, transfer_type);
    167182                return ENOTSUP;
    168183        }
     
    193208        td->callback = job;
    194209
    195         usb_log_debug("Appending a new transfer to queue.\n");
    196         ret = transfer_list_append(&instance->transfers[transfer_type], td);
     210
     211        usb_log_debug("Appending a new transfer to queue %s.\n", list->name);
     212
     213        ret = transfer_list_append(list, td);
    197214        CHECK_RET_TRANS_FREE_JOB_TD("Failed to append transfer descriptor.\n");
    198215
     
    209226                usb_log_debug("Running cleaning fibril on: %p.\n", instance);
    210227                /* iterate all transfer queues */
    211                 int i = 0;
    212                 for (; i < TRANSFER_QUEUES; ++i) {
     228                transfer_list_t *current_list = &instance->transfers_interrupt;
     229                while (current_list) {
    213230                        /* Remove inactive transfers from the top of the queue
    214231                         * TODO: should I reach queue head or is this enough? */
    215232                        volatile transfer_descriptor_t * it =
    216                                 instance->transfers[i].first;
    217                         usb_log_debug("Running cleaning fibril on queue: %p (%s).\n",
    218                                 &instance->transfers[i], it ? "SOMETHING" : "EMPTY");
     233                                current_list->first;
     234                        usb_log_debug("Running cleaning fibril on queue: %s (%s).\n",
     235                                current_list->name, it ? "SOMETHING" : "EMPTY");
    219236
    220237                        if (it)
     
    222239                                        it, it->status);
    223240
    224                         while (instance->transfers[i].first &&
    225                          !(instance->transfers[i].first->status & TD_STATUS_ERROR_ACTIVE)) {
    226                                 transfer_descriptor_t *transfer = instance->transfers[i].first;
     241                        while (current_list->first &&
     242                         !(current_list->first->status & TD_STATUS_ERROR_ACTIVE)) {
     243                                transfer_descriptor_t *transfer = current_list->first;
    227244                                usb_log_info("Inactive transfer calling callback with status %x.\n",
    228245                                  transfer->status);
    229                                 instance->transfers[i].first = transfer->next_va;
     246                                current_list->first = transfer->next_va;
    230247                                transfer_descriptor_dispose(transfer);
    231248                        }
    232                         if (!instance->transfers[i].first)
    233                                 instance->transfers[i].last = instance->transfers[i].first;
     249                        if (!current_list->first)
     250                                current_list->last = current_list->first;
     251
     252                        current_list = current_list->next;
    234253                }
    235254                async_usleep(UHCI_CLEANER_TIMEOUT);
     
    246265                uint16_t sts = pio_read_16(&instance->registers->usbsts);
    247266                usb_log_debug("Command register: %X Status register: %X\n", cmd, sts);
    248 /*
     267
    249268                uintptr_t frame_list = pio_read_32(&instance->registers->flbaseadd);
    250269                usb_log_debug("Framelist address: %p vs. %p.\n",
     
    253272                usb_log_debug("Framelist item: %d \n", frnum );
    254273
    255                 queue_head_t* qh = instance->transfers[USB_TRANSFER_INTERRUPT].queue_head;
    256                 usb_log_debug("Interrupt QH: %p vs. %p.\n",
    257                         instance->frame_list[frnum], addr_to_phys(qh));
    258 
    259                 usb_log_debug("Control QH: %p vs. %p.\n", qh->next_queue,
    260                         addr_to_phys(instance->transfers[USB_TRANSFER_CONTROL].queue_head));
    261                 qh = instance->transfers[USB_TRANSFER_CONTROL].queue_head;
    262 
    263                 usb_log_debug("Bulk QH: %p vs. %p.\n", qh->next_queue,
    264                         addr_to_phys(instance->transfers[USB_TRANSFER_BULK].queue_head));
     274                queue_head_t* qh = instance->transfers_interrupt.queue_head;
     275
     276                if ((instance->frame_list[frnum] & (~0xf)) != (uintptr_t)addr_to_phys(qh)) {
     277                        usb_log_debug("Interrupt QH: %p vs. %p.\n",
     278                                instance->frame_list[frnum] & (~0xf), addr_to_phys(qh));
     279                }
     280
     281                if ((qh->next_queue & (~0xf))
     282                  != (uintptr_t)addr_to_phys(instance->transfers_control_slow.queue_head)) {
     283                        usb_log_debug("Control Slow QH: %p vs. %p.\n", qh->next_queue & (~0xf),
     284                                addr_to_phys(instance->transfers_control_slow.queue_head));
     285                }
     286                qh = instance->transfers_control_slow.queue_head;
     287
     288                if ((qh->next_queue & (~0xf))
     289                  != (uintptr_t)addr_to_phys(instance->transfers_control_full.queue_head)) {
     290                        usb_log_debug("Control Full QH: %p vs. %p.\n", qh->next_queue & (~0xf),
     291                                addr_to_phys(instance->transfers_control_full.queue_head));\
     292                }
     293                qh = instance->transfers_control_full.queue_head;
     294
     295                if ((qh->next_queue & (~0xf))
     296                  != (uintptr_t)addr_to_phys(instance->transfers_bulk_full.queue_head)) {
     297                        usb_log_debug("Bulk QH: %p vs. %p.\n", qh->next_queue & (~0xf),
     298                                addr_to_phys(instance->transfers_bulk_full.queue_head));
     299                }
     300/*
    265301        uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
    266302        cmd |= UHCI_CMD_RUN_STOP;
    267303        pio_write_16(&instance->registers->usbcmd, cmd);
    268304*/
    269 
    270305                async_usleep(UHCI_DEBUGER_TIMEOUT);
    271306        }
  • uspace/drv/uhci-hcd/uhci.h

    r97e87de r881c47b  
    7979        link_pointer_t *frame_list;
    8080
    81         transfer_list_t transfers[TRANSFER_QUEUES];
     81        transfer_list_t transfers_bulk_full;
     82        transfer_list_t transfers_control_full;
     83        transfer_list_t transfers_control_slow;
     84        transfer_list_t transfers_interrupt;
     85
     86        transfer_list_t *transfers[2][4];
     87
    8288        fid_t cleaner;
    8389        fid_t debug_checker;
     
    96102        bool toggle,
    97103  usb_packet_id pid,
     104        bool low_speed,
    98105  void *buffer, size_t size,
    99106  usbhc_iface_transfer_out_callback_t callback_out,
  • uspace/drv/uhci-hcd/uhci_struct/queue_head.h

    r97e87de r881c47b  
    4747} __attribute__((packed)) queue_head_t;
    4848
    49 static inline void queue_head_init(queue_head_t *instance, uint32_t next_queue_pa)
     49static inline void queue_head_init(queue_head_t *instance)
    5050{
    5151        assert(instance);
    52         assert((next_queue_pa & LINK_POINTER_ADDRESS_MASK) == next_queue_pa);
    5352
    5453        instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
     54        instance->next_queue = 0 | LINK_POINTER_TERMINATE_FLAG;
     55}
     56
     57static inline void queue_head_add_next(queue_head_t *instance, uint32_t next_queue_pa)
     58{
    5559        if (next_queue_pa) {
    5660                instance->next_queue = (next_queue_pa & LINK_POINTER_ADDRESS_MASK)
    5761                  | LINK_POINTER_QUEUE_HEAD_FLAG;
    58         } else {
    59                 instance->next_queue = 0 | LINK_POINTER_TERMINATE_FLAG;
    6062        }
    6163}
Note: See TracChangeset for help on using the changeset viewer.