Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ehci/hc.c

    rb7fd2a0 r5a6cc679  
    4545#include <usb/debug.h>
    4646#include <usb/usb.h>
    47 #include <usb/host/utils/malloc32.h>
     47#include <usb/host/utility.h>
    4848
    4949#include "ehci_batch.h"
     
    8989};
    9090
    91 static void hc_start(hc_t *instance);
    9291static errno_t hc_init_memory(hc_t *instance);
    9392
     
    10099 * @return Error code.
    101100 */
    102 errno_t ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res, int *irq)
     101errno_t hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res, int *irq)
    103102{
    104103        assert(code);
    105104        assert(hw_res);
     105        hc_t *instance = hcd_to_hc(hcd);
    106106
    107107        if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1)
     
    130130
    131131        memcpy(code->cmds, ehci_irq_commands, sizeof(ehci_irq_commands));
    132         ehci_caps_regs_t *caps = NULL;
    133 
    134         errno_t ret = pio_enable_range(&regs, (void**)&caps);
    135         if (ret != EOK) {
    136                 free(code->ranges);
    137                 free(code->cmds);
    138                 return ret;
    139         }
    140132
    141133        ehci_regs_t *registers =
    142             (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(caps->caplength));
     134                (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(instance->caps->caplength));
    143135        code->cmds[0].addr = (void *) &registers->usbsts;
    144136        code->cmds[3].addr = (void *) &registers->usbsts;
    145137        EHCI_WR(code->cmds[1].value, EHCI_USED_INTERRUPTS);
    146138
    147         usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
     139        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.",
    148140            RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]);
    149141
     
    159151 * @return Error code
    160152 */
    161 errno_t hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
    162 {
    163         assert(instance);
     153errno_t hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
     154{
     155        hc_t *instance = hcd_to_hc(hcd);
    164156        assert(hw_res);
    165157        if (hw_res->mem_ranges.count != 1 ||
     
    172164        if (ret != EOK) {
    173165                usb_log_error("HC(%p): Failed to gain access to device "
    174                     "registers: %s.\n", instance, str_error(ret));
     166                    "registers: %s.", instance, str_error(ret));
    175167                return ret;
    176168        }
     169
    177170        usb_log_info("HC(%p): Device registers at %"PRIx64" (%zuB) accessible.",
    178171            instance, hw_res->mem_ranges.ranges[0].address.absolute,
     
    184177            + EHCI_RD8(instance->caps->caplength));
    185178
    186         list_initialize(&instance->pending_batches);
     179        list_initialize(&instance->pending_endpoints);
    187180        fibril_mutex_initialize(&instance->guard);
    188181        fibril_condvar_initialize(&instance->async_doorbell);
     
    197190        usb_log_info("HC(%p): Initializing RH(%p).", instance, &instance->rh);
    198191        ehci_rh_init(
    199             &instance->rh, instance->caps, instance->registers, "ehci rh");
    200         usb_log_debug("HC(%p): Starting HW.", instance);
    201         hc_start(instance);
    202 
     192            &instance->rh, instance->caps, instance->registers, &instance->guard,
     193            "ehci rh");
     194
     195        ehci_bus_init(&instance->bus, instance);
     196        hc_device_setup(hcd, (bus_t *) &instance->bus);
    203197        return EOK;
    204198}
     
    208202 * @param[in] instance Host controller structure to use.
    209203 */
    210 void hc_fini(hc_t *instance)
    211 {
    212         assert(instance);
    213         //TODO: stop the hw
    214 #if 0
    215         endpoint_list_fini(&instance->async_list);
    216         endpoint_list_fini(&instance->int_list);
    217         return_page(instance->periodic_list_base);
    218 #endif
     204int hc_gone(hc_device_t *hcd)
     205{
     206        hc_t *hc = hcd_to_hc(hcd);
     207        endpoint_list_fini(&hc->async_list);
     208        endpoint_list_fini(&hc->int_list);
     209        dma_buffer_free(&hc->dma_buffer);
     210        return EOK;
    219211};
    220212
     
    224216        assert(ep);
    225217        ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep);
    226         usb_log_debug("HC(%p) enqueue EP(%d:%d:%s:%s)\n", instance,
    227             ep->address, ep->endpoint,
     218        usb_log_debug("HC(%p) enqueue EP(%d:%d:%s:%s)", instance,
     219            ep->device->address, ep->endpoint,
    228220            usb_str_transfer_type_short(ep->transfer_type),
    229221            usb_str_direction(ep->direction));
     
    248240        assert(ep);
    249241        ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep);
    250         usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s)\n", instance,
    251             ep->address, ep->endpoint,
     242        usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s)", instance,
     243            ep->device->address, ep->endpoint,
    252244            usb_str_transfer_type_short(ep->transfer_type),
    253245            usb_str_direction(ep->direction));
     
    273265}
    274266
    275 errno_t ehci_hc_status(hcd_t *hcd, uint32_t *status)
    276 {
    277         assert(hcd);
    278         hc_t *instance = hcd_get_driver_data(hcd);
    279         assert(instance);
     267errno_t ehci_hc_status(bus_t *bus_base, uint32_t *status)
     268{
     269        assert(bus_base);
    280270        assert(status);
     271
     272        ehci_bus_t *bus = (ehci_bus_t *) bus_base;
     273        hc_t *hc = bus->hc;
     274        assert(hc);
     275
    281276        *status = 0;
    282         if (instance->registers) {
    283                 *status = EHCI_RD(instance->registers->usbsts);
    284                 EHCI_WR(instance->registers->usbsts, *status);
    285         }
    286         usb_log_debug2("HC(%p): Read status: %x", instance, *status);
     277        if (hc->registers) {
     278                *status = EHCI_RD(hc->registers->usbsts);
     279                EHCI_WR(hc->registers->usbsts, *status);
     280        }
     281        usb_log_debug2("HC(%p): Read status: %x", hc, *status);
    287282        return EOK;
    288283}
     
    294289 * @return Error code.
    295290 */
    296 errno_t ehci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    297 {
    298         assert(hcd);
    299         hc_t *instance = hcd_get_driver_data(hcd);
    300         assert(instance);
     291errno_t ehci_hc_schedule(usb_transfer_batch_t *batch)
     292{
     293        assert(batch);
     294
     295        ehci_bus_t *bus = (ehci_bus_t *) endpoint_get_bus(batch->ep);
     296        hc_t *hc = bus->hc;
     297        assert(hc);
    301298
    302299        /* Check for root hub communication */
    303         if (batch->ep->address == ehci_rh_get_address(&instance->rh)) {
     300        if (batch->target.address == ehci_rh_get_address(&hc->rh)) {
    304301                usb_log_debug("HC(%p): Scheduling BATCH(%p) for RH(%p)",
    305                     instance, batch, &instance->rh);
    306                 return ehci_rh_schedule(&instance->rh, batch);
    307         }
     302                    hc, batch, &hc->rh);
     303                return ehci_rh_schedule(&hc->rh, batch);
     304        }
     305
     306        endpoint_t * const ep = batch->ep;
     307        ehci_endpoint_t * const ehci_ep = ehci_endpoint_get(ep);
    308308        ehci_transfer_batch_t *ehci_batch = ehci_transfer_batch_get(batch);
    309         if (!ehci_batch)
    310                 return ENOMEM;
    311 
    312         fibril_mutex_lock(&instance->guard);
    313         usb_log_debug2("HC(%p): Appending BATCH(%p)", instance, batch);
    314         list_append(&ehci_batch->link, &instance->pending_batches);
    315         usb_log_debug("HC(%p): Committing BATCH(%p)", instance, batch);
     309
     310        int err;
     311
     312        if ((err = ehci_transfer_batch_prepare(ehci_batch)))
     313                return err;
     314
     315        fibril_mutex_lock(&hc->guard);
     316
     317        if ((err = endpoint_activate_locked(ep, batch))) {
     318                fibril_mutex_unlock(&hc->guard);
     319                return err;
     320        }
     321
     322        usb_log_debug("HC(%p): Committing BATCH(%p)", hc, batch);
    316323        ehci_transfer_batch_commit(ehci_batch);
    317324
    318         fibril_mutex_unlock(&instance->guard);
     325        /* Enqueue endpoint to the checked list */
     326        usb_log_debug2("HC(%p): Appending BATCH(%p)", hc, batch);
     327        list_append(&ehci_ep->pending_link, &hc->pending_endpoints);
     328
     329        fibril_mutex_unlock(&hc->guard);
    319330        return EOK;
    320331}
     
    325336 * @param[in] status Value of the status register at the time of interrupt.
    326337 */
    327 void ehci_hc_interrupt(hcd_t *hcd, uint32_t status)
    328 {
    329         assert(hcd);
    330         hc_t *instance = hcd_get_driver_data(hcd);
    331         status = EHCI_RD(status);
    332         assert(instance);
    333 
    334         usb_log_debug2("HC(%p): Interrupt: %"PRIx32, instance, status);
     338void ehci_hc_interrupt(bus_t *bus_base, uint32_t status)
     339{
     340        assert(bus_base);
     341
     342        ehci_bus_t *bus = (ehci_bus_t *) bus_base;
     343        hc_t *hc = bus->hc;
     344        assert(hc);
     345
     346        usb_log_debug2("HC(%p): Interrupt: %"PRIx32, hc, status);
    335347        if (status & USB_STS_PORT_CHANGE_FLAG) {
    336                 ehci_rh_interrupt(&instance->rh);
     348                ehci_rh_interrupt(&hc->rh);
    337349        }
    338350
    339351        if (status & USB_STS_IRQ_ASYNC_ADVANCE_FLAG) {
    340                 fibril_mutex_lock(&instance->guard);
    341                 usb_log_debug2("HC(%p): Signaling doorbell", instance);
    342                 fibril_condvar_broadcast(&instance->async_doorbell);
    343                 fibril_mutex_unlock(&instance->guard);
     352                fibril_mutex_lock(&hc->guard);
     353                usb_log_debug2("HC(%p): Signaling doorbell", hc);
     354                fibril_condvar_broadcast(&hc->async_doorbell);
     355                fibril_mutex_unlock(&hc->guard);
    344356        }
    345357
    346358        if (status & (USB_STS_IRQ_FLAG | USB_STS_ERR_IRQ_FLAG)) {
    347                 fibril_mutex_lock(&instance->guard);
    348 
    349                 usb_log_debug2("HC(%p): Scanning %lu pending batches", instance,
    350                         list_count(&instance->pending_batches));
    351                 list_foreach_safe(instance->pending_batches, current, next) {
    352                         ehci_transfer_batch_t *batch =
    353                             ehci_transfer_batch_from_link(current);
    354 
    355                         if (ehci_transfer_batch_is_complete(batch)) {
     359                fibril_mutex_lock(&hc->guard);
     360
     361                usb_log_debug2("HC(%p): Scanning %lu pending endpoints", hc,
     362                        list_count(&hc->pending_endpoints));
     363                list_foreach_safe(hc->pending_endpoints, current, next) {
     364                        ehci_endpoint_t *ep
     365                                = list_get_instance(current, ehci_endpoint_t, pending_link);
     366
     367                        ehci_transfer_batch_t *batch
     368                                = ehci_transfer_batch_get(ep->base.active_batch);
     369                        assert(batch);
     370
     371                        if (ehci_transfer_batch_check_completed(batch)) {
     372                                endpoint_deactivate_locked(&ep->base);
    356373                                list_remove(current);
    357                                 ehci_transfer_batch_finish_dispose(batch);
     374                                hc_reset_toggles(&batch->base, &ehci_ep_toggle_reset);
     375                                usb_transfer_batch_finish(&batch->base);
    358376                        }
    359377                }
    360                 fibril_mutex_unlock(&instance->guard);
     378                fibril_mutex_unlock(&hc->guard);
     379
     380
    361381        }
    362382
    363383        if (status & USB_STS_HOST_ERROR_FLAG) {
    364                 usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", instance);
     384                usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", hc);
    365385                //TODO do something here
    366386        }
     
    371391 * @param[in] instance EHCI hc driver structure.
    372392 */
    373 void hc_start(hc_t *instance)
    374 {
    375         assert(instance);
     393int hc_start(hc_device_t *hcd)
     394{
     395        hc_t *instance = hcd_to_hc(hcd);
     396        usb_log_debug("HC(%p): Starting HW.", instance);
     397
    376398        /* Turn off the HC if it's running, Reseting a running device is
    377399         * undefined */
     
    404426
    405427        /* Enable periodic list */
    406         assert(instance->periodic_list_base);
     428        assert(instance->periodic_list);
    407429        uintptr_t phys_base =
    408             addr_to_phys((void*)instance->periodic_list_base);
     430            addr_to_phys((void*)instance->periodic_list);
    409431        assert((phys_base & USB_PERIODIC_LIST_BASE_MASK) == phys_base);
    410432        EHCI_WR(instance->registers->periodiclistbase, phys_base);
     
    425447        usb_log_debug("HC(%p): HW started.", instance);
    426448
    427         usb_log_debug2("HC(%p): Registers: \n"
    428             "\tUSBCMD(%p): %x(0x00080000 = at least 1ms between interrupts)\n"
    429             "\tUSBSTS(%p): %x(0x00001000 = HC halted)\n"
    430             "\tUSBINT(%p): %x(0x0 = no interrupts).\n"
    431             "\tCONFIG(%p): %x(0x0 = ports controlled by companion hc).\n",
     449        usb_log_debug2("HC(%p): Registers: "
     450            "\tUSBCMD(%p): %x(0x00080000 = at least 1ms between interrupts)"
     451            "\tUSBSTS(%p): %x(0x00001000 = HC halted)"
     452            "\tUSBINT(%p): %x(0x0 = no interrupts)."
     453            "\tCONFIG(%p): %x(0x0 = ports controlled by companion hc).",
    432454            instance,
    433455            &instance->registers->usbcmd, EHCI_RD(instance->registers->usbcmd),
     
    438460        EHCI_WR(instance->registers->usbsts, EHCI_RD(instance->registers->usbsts));
    439461        EHCI_WR(instance->registers->usbintr, EHCI_USED_INTERRUPTS);
     462
     463        return EOK;
     464}
     465
     466/**
     467 * Setup roothub as a virtual hub.
     468 */
     469int hc_setup_roothub(hc_device_t *hcd)
     470{
     471        return hc_setup_virtual_root_hub(hcd, USB_SPEED_HIGH);
    440472}
    441473
     
    473505
    474506        /* Take 1024 periodic list heads, we ignore low mem options */
    475         instance->periodic_list_base = get_page();
    476         if (!instance->periodic_list_base) {
     507        if (dma_buffer_alloc(&instance->dma_buffer, PAGE_SIZE)) {
    477508                usb_log_error("HC(%p): Failed to get ISO schedule page.",
    478509                    instance);
     
    481512                return ENOMEM;
    482513        }
     514        instance->periodic_list = instance->dma_buffer.virt;
    483515
    484516        usb_log_debug2("HC(%p): Initializing Periodic list.", instance);
    485         for (unsigned i = 0;
    486             i < PAGE_SIZE/sizeof(instance->periodic_list_base[0]); ++i)
     517        for (unsigned i = 0; i < PAGE_SIZE/sizeof(link_pointer_t); ++i)
    487518        {
    488519                /* Disable everything for now */
    489                 instance->periodic_list_base[i] =
     520                instance->periodic_list[i] =
    490521                    LINK_POINTER_QH(addr_to_phys(instance->int_list.list_head));
    491522        }
Note: See TracChangeset for help on using the changeset viewer.