Changeset 651b352 in mainline for uspace/drv/ohci/hc.c


Ignore:
Timestamp:
2011-04-13T15:00:43Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8b4ce802
Parents:
4deca9b (diff), d6522dd (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Major rework

UHCI uses one buffer for both structures and data
OHCI uses new architecture that actually follows OHCI specification

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/ohci/hc.c

    r4deca9b r651b352  
    4343
    4444#include "hc.h"
     45#include "hcd_endpoint.h"
    4546
    4647static int interrupt_emulator(hc_t *instance);
     
    6768            &instance->manager, hub_address, hub_fun->handle);
    6869
    69         ret = usb_endpoint_manager_add_ep(&instance->ep_manager,
    70             hub_address, 0, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
    71             USB_SPEED_FULL, 64, 0);
     70        ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
     71            USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
    7272        if (ret != EOK) {
    7373                usb_log_error("Failed to add OHCI rh endpoint 0.\n");
     
    109109            ret, str_error(ret));
    110110
    111         instance->ddf_instance = fun;
    112111        usb_device_keeper_init(&instance->manager);
    113112        ret = usb_endpoint_manager_init(&instance->ep_manager,
     
    131130        }
    132131
    133         return EOK;
     132        list_initialize(&instance->pending_batches);
     133#undef CHECK_RET_RETURN
     134        return EOK;
     135}
     136/*----------------------------------------------------------------------------*/
     137int hc_add_endpoint(
     138    hc_t *instance, usb_address_t address, usb_endpoint_t endpoint,
     139    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
     140    size_t mps, size_t size, unsigned interval)
     141{
     142        endpoint_t *ep = malloc(sizeof(endpoint_t));
     143        if (ep == NULL)
     144                return ENOMEM;
     145        int ret =
     146            endpoint_init(ep, address, endpoint, direction, type, speed, mps);
     147        if (ret != EOK) {
     148                free(ep);
     149                return ret;
     150        }
     151
     152        hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
     153        if (hcd_ep == NULL) {
     154                endpoint_destroy(ep);
     155                return ENOMEM;
     156        }
     157
     158        ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
     159        if (ret != EOK) {
     160                hcd_endpoint_clear(ep);
     161                endpoint_destroy(ep);
     162                return ret;
     163        }
     164
     165        /* Enqueue hcd_ep */
     166        switch (ep->transfer_type) {
     167        case USB_TRANSFER_CONTROL:
     168                instance->registers->control &= ~C_CLE;
     169                endpoint_list_add_ep(
     170                    &instance->lists[ep->transfer_type], hcd_ep);
     171                instance->registers->control_current = 0;
     172                instance->registers->control |= C_CLE;
     173                break;
     174        case USB_TRANSFER_BULK:
     175                instance->registers->control &= ~C_BLE;
     176                endpoint_list_add_ep(
     177                    &instance->lists[ep->transfer_type], hcd_ep);
     178                instance->registers->control |= C_BLE;
     179                break;
     180        case USB_TRANSFER_ISOCHRONOUS:
     181        case USB_TRANSFER_INTERRUPT:
     182                instance->registers->control &= (~C_PLE & ~C_IE);
     183                endpoint_list_add_ep(
     184                    &instance->lists[ep->transfer_type], hcd_ep);
     185                instance->registers->control |= C_PLE | C_IE;
     186                break;
     187        default:
     188                break;
     189        }
     190
     191        return EOK;
     192}
     193/*----------------------------------------------------------------------------*/
     194int hc_remove_endpoint(hc_t *instance, usb_address_t address,
     195    usb_endpoint_t endpoint, usb_direction_t direction)
     196{
     197        assert(instance);
     198        fibril_mutex_lock(&instance->guard);
     199        endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
     200            address, endpoint, direction, NULL);
     201        if (ep == NULL) {
     202                usb_log_error("Endpoint unregister failed: No such EP.\n");
     203                fibril_mutex_unlock(&instance->guard);
     204                return ENOENT;
     205        }
     206
     207        hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
     208        if (hcd_ep) {
     209                /* Dequeue hcd_ep */
     210                switch (ep->transfer_type) {
     211                case USB_TRANSFER_CONTROL:
     212                        instance->registers->control &= ~C_CLE;
     213                        endpoint_list_remove_ep(
     214                            &instance->lists[ep->transfer_type], hcd_ep);
     215                        instance->registers->control_current = 0;
     216                        instance->registers->control |= C_CLE;
     217                        break;
     218                case USB_TRANSFER_BULK:
     219                        instance->registers->control &= ~C_BLE;
     220                        endpoint_list_remove_ep(
     221                            &instance->lists[ep->transfer_type], hcd_ep);
     222                        instance->registers->control |= C_BLE;
     223                        break;
     224                case USB_TRANSFER_ISOCHRONOUS:
     225                case USB_TRANSFER_INTERRUPT:
     226                        instance->registers->control &= (~C_PLE & ~C_IE);
     227                        endpoint_list_remove_ep(
     228                            &instance->lists[ep->transfer_type], hcd_ep);
     229                        instance->registers->control |= C_PLE | C_IE;
     230                        break;
     231                default:
     232                        break;
     233                }
     234                hcd_endpoint_clear(ep);
     235        } else {
     236                usb_log_warning("Endpoint without hcd equivalent structure.\n");
     237        }
     238        int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager,
     239            address, endpoint, direction);
     240        fibril_mutex_unlock(&instance->guard);
     241        return ret;
     242}
     243/*----------------------------------------------------------------------------*/
     244endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
     245    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw)
     246{
     247        assert(instance);
     248        fibril_mutex_lock(&instance->guard);
     249        endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
     250            address, endpoint, direction, bw);
     251        fibril_mutex_unlock(&instance->guard);
     252        return ep;
    134253}
    135254/*----------------------------------------------------------------------------*/
     
    146265
    147266        fibril_mutex_lock(&instance->guard);
     267        list_append(&batch->link, &instance->pending_batches);
     268        batch_commit(batch);
    148269        switch (batch->ep->transfer_type) {
    149270        case USB_TRANSFER_CONTROL:
    150                 instance->registers->control &= ~C_CLE;
    151                 transfer_list_add_batch(
    152                     instance->transfers[batch->ep->transfer_type], batch);
    153271                instance->registers->command_status |= CS_CLF;
    154                 usb_log_debug2("Set CS control transfer filled: %x.\n",
    155                         instance->registers->command_status);
    156                 instance->registers->control_current = 0;
    157                 instance->registers->control |= C_CLE;
    158272                break;
    159273        case USB_TRANSFER_BULK:
    160                 instance->registers->control &= ~C_BLE;
    161                 transfer_list_add_batch(
    162                     instance->transfers[batch->ep->transfer_type], batch);
    163274                instance->registers->command_status |= CS_BLF;
    164                 usb_log_debug2("Set bulk transfer filled: %x.\n",
    165                         instance->registers->command_status);
    166                 instance->registers->control |= C_BLE;
    167                 break;
    168         case USB_TRANSFER_INTERRUPT:
    169         case USB_TRANSFER_ISOCHRONOUS:
    170                 instance->registers->control &= (~C_PLE & ~C_IE);
    171                 transfer_list_add_batch(
    172                     instance->transfers[batch->ep->transfer_type], batch);
    173                 instance->registers->control |= C_PLE | C_IE;
    174                 usb_log_debug2("Added periodic transfer: %x.\n",
    175                     instance->registers->periodic_current);
    176275                break;
    177276        default:
    178277                break;
    179278        }
     279
    180280        fibril_mutex_unlock(&instance->guard);
    181281        return EOK;
     
    198298                usb_log_debug2("Periodic current: %p.\n",
    199299                    instance->registers->periodic_current);
    200                 LIST_INITIALIZE(done);
    201                 transfer_list_remove_finished(
    202                     &instance->transfers_interrupt, &done);
    203                 transfer_list_remove_finished(
    204                     &instance->transfers_isochronous, &done);
    205                 transfer_list_remove_finished(
    206                     &instance->transfers_control, &done);
    207                 transfer_list_remove_finished(
    208                     &instance->transfers_bulk, &done);
    209 
    210                 while (!list_empty(&done)) {
    211                         link_t *item = done.next;
    212                         list_remove(item);
     300
     301                link_t *current = instance->pending_batches.next;
     302                while (current != &instance->pending_batches) {
     303                        link_t *next = current->next;
    213304                        usb_transfer_batch_t *batch =
    214                             list_get_instance(item, usb_transfer_batch_t, link);
    215                         usb_transfer_batch_finish(batch);
     305                            usb_transfer_batch_from_link(current);
     306
     307                        if (batch_is_complete(batch)) {
     308                                list_remove(current);
     309                                usb_transfer_batch_finish(batch);
     310                        }
     311                        current = next;
    216312                }
    217313                fibril_mutex_unlock(&instance->guard);
     
    307403
    308404        /* Use queues */
    309         instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
     405        instance->registers->bulk_head =
     406            instance->lists[USB_TRANSFER_BULK].list_head_pa;
    310407        usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
    311             instance->transfers_bulk.list_head,
    312             instance->transfers_bulk.list_head_pa);
     408            instance->lists[USB_TRANSFER_BULK].list_head,
     409            instance->lists[USB_TRANSFER_BULK].list_head_pa);
    313410
    314411        instance->registers->control_head =
    315             instance->transfers_control.list_head_pa;
     412            instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
    316413        usb_log_debug2("Control HEAD set to: %p(%p).\n",
    317             instance->transfers_control.list_head,
    318             instance->transfers_control.list_head_pa);
     414            instance->lists[USB_TRANSFER_CONTROL].list_head,
     415            instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
    319416
    320417        /* Enable queues */
     
    347444        assert(instance);
    348445
    349 #define SETUP_TRANSFER_LIST(type, name) \
     446#define SETUP_ENDPOINT_LIST(type) \
    350447do { \
    351         int ret = transfer_list_init(&instance->type, name); \
     448        const char *name = usb_str_transfer_type(type); \
     449        int ret = endpoint_list_init(&instance->lists[type], name); \
    352450        if (ret != EOK) { \
    353                 usb_log_error("Failed(%d) to setup %s transfer list.\n", \
     451                usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
    354452                    ret, name); \
    355                 transfer_list_fini(&instance->transfers_isochronous); \
    356                 transfer_list_fini(&instance->transfers_interrupt); \
    357                 transfer_list_fini(&instance->transfers_control); \
    358                 transfer_list_fini(&instance->transfers_bulk); \
     453                endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \
     454                endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
     455                endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \
     456                endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \
    359457        } \
    360458} while (0)
    361459
    362         SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS");
    363         SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT");
    364         SETUP_TRANSFER_LIST(transfers_control, "CONTROL");
    365         SETUP_TRANSFER_LIST(transfers_bulk, "BULK");
    366 #undef SETUP_TRANSFER_LIST
    367         transfer_list_set_next(&instance->transfers_interrupt,
    368             &instance->transfers_isochronous);
    369 
    370         /* Assign pointers to be used during scheduling */
    371         instance->transfers[USB_TRANSFER_INTERRUPT] =
    372           &instance->transfers_interrupt;
    373         instance->transfers[USB_TRANSFER_ISOCHRONOUS] =
    374           &instance->transfers_interrupt;
    375         instance->transfers[USB_TRANSFER_CONTROL] =
    376           &instance->transfers_control;
    377         instance->transfers[USB_TRANSFER_BULK] =
    378           &instance->transfers_bulk;
     460        SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS);
     461        SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT);
     462        SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL);
     463        SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK);
     464#undef SETUP_ENDPOINT_LIST
     465        endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT],
     466            &instance->lists[USB_TRANSFER_ISOCHRONOUS]);
    379467
    380468        return EOK;
     
    397485        for (; i < 32; ++i) {
    398486                instance->hcca->int_ep[i] =
    399                     instance->transfers_interrupt.list_head_pa;
     487                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
    400488        }
    401489        usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
    402             instance->transfers_interrupt.list_head,
    403             instance->transfers_interrupt.list_head_pa);
     490            instance->lists[USB_TRANSFER_INTERRUPT].list_head,
     491            instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
    404492
    405493        return EOK;
Note: See TracChangeset for help on using the changeset viewer.