Ignore:
File:
1 edited

Legend:

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

    r68e5406 rddbd088  
    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 int hc_init_memory(hc_t *instance);
    9392
     
    9695 * @param[in] hw_res Device's resources.
    9796 *
    98  * @param[out] irq
    99  *
    10097 * @return Error code.
    10198 */
    102 int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res, int *irq)
     99int hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
    103100{
    104101        assert(code);
    105102        assert(hw_res);
     103        hc_t *instance = hcd_to_hc(hcd);
    106104
    107105        if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1)
     
    130128
    131129        memcpy(code->cmds, ehci_irq_commands, sizeof(ehci_irq_commands));
    132         ehci_caps_regs_t *caps = NULL;
    133 
    134         int ret = pio_enable_range(&regs, (void**)&caps);
    135         if (ret != EOK) {
    136                 free(code->ranges);
    137                 free(code->cmds);
    138                 return ret;
    139         }
    140130
    141131        ehci_regs_t *registers =
    142             (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(caps->caplength));
     132                (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(instance->caps->caplength));
    143133        code->cmds[0].addr = (void *) &registers->usbsts;
    144134        code->cmds[3].addr = (void *) &registers->usbsts;
    145135        EHCI_WR(code->cmds[1].value, EHCI_USED_INTERRUPTS);
    146136
    147         usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
     137        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.",
    148138            RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]);
    149139
    150         *irq = hw_res->irqs.irqs[0];
    151         return EOK;
     140        return hw_res->irqs.irqs[0];
    152141}
    153142
     
    159148 * @return Error code
    160149 */
    161 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
    162 {
    163         assert(instance);
     150int hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
     151{
     152        hc_t *instance = hcd_to_hc(hcd);
    164153        assert(hw_res);
    165154        if (hw_res->mem_ranges.count != 1 ||
     
    172161        if (ret != EOK) {
    173162                usb_log_error("HC(%p): Failed to gain access to device "
    174                     "registers: %s.\n", instance, str_error(ret));
     163                    "registers: %s.", instance, str_error(ret));
    175164                return ret;
    176165        }
     166
    177167        usb_log_info("HC(%p): Device registers at %"PRIx64" (%zuB) accessible.",
    178168            instance, hw_res->mem_ranges.ranges[0].address.absolute,
     
    184174            + EHCI_RD8(instance->caps->caplength));
    185175
    186         list_initialize(&instance->pending_batches);
     176        list_initialize(&instance->pending_endpoints);
    187177        fibril_mutex_initialize(&instance->guard);
    188178        fibril_condvar_initialize(&instance->async_doorbell);
     
    197187        usb_log_info("HC(%p): Initializing RH(%p).", instance, &instance->rh);
    198188        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 
     189            &instance->rh, instance->caps, instance->registers, &instance->guard,
     190            "ehci rh");
     191
     192        ehci_bus_init(&instance->bus, instance);
     193        hc_device_setup(hcd, (bus_t *) &instance->bus);
    203194        return EOK;
    204195}
     
    208199 * @param[in] instance Host controller structure to use.
    209200 */
    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
     201int hc_gone(hc_device_t *hcd)
     202{
     203        hc_t *hc = hcd_to_hc(hcd);
     204        endpoint_list_fini(&hc->async_list);
     205        endpoint_list_fini(&hc->int_list);
     206        dma_buffer_free(&hc->dma_buffer);
     207        return EOK;
    219208};
    220209
     
    224213        assert(ep);
    225214        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,
     215        usb_log_debug("HC(%p) enqueue EP(%d:%d:%s:%s)", instance,
     216            ep->device->address, ep->endpoint,
    228217            usb_str_transfer_type_short(ep->transfer_type),
    229218            usb_str_direction(ep->direction));
     
    248237        assert(ep);
    249238        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,
     239        usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s)", instance,
     240            ep->device->address, ep->endpoint,
    252241            usb_str_transfer_type_short(ep->transfer_type),
    253242            usb_str_direction(ep->direction));
     
    273262}
    274263
    275 int 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);
     264int ehci_hc_status(bus_t *bus_base, uint32_t *status)
     265{
     266        assert(bus_base);
    280267        assert(status);
     268
     269        ehci_bus_t *bus = (ehci_bus_t *) bus_base;
     270        hc_t *hc = bus->hc;
     271        assert(hc);
     272
    281273        *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);
     274        if (hc->registers) {
     275                *status = EHCI_RD(hc->registers->usbsts);
     276                EHCI_WR(hc->registers->usbsts, *status);
     277        }
     278        usb_log_debug2("HC(%p): Read status: %x", hc, *status);
    287279        return EOK;
    288280}
     
    294286 * @return Error code.
    295287 */
    296 int 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);
     288int ehci_hc_schedule(usb_transfer_batch_t *batch)
     289{
     290        assert(batch);
     291
     292        ehci_bus_t *bus = (ehci_bus_t *) endpoint_get_bus(batch->ep);
     293        hc_t *hc = bus->hc;
     294        assert(hc);
    301295
    302296        /* Check for root hub communication */
    303         if (batch->ep->address == ehci_rh_get_address(&instance->rh)) {
     297        if (batch->target.address == ehci_rh_get_address(&hc->rh)) {
    304298                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         }
     299                    hc, batch, &hc->rh);
     300                return ehci_rh_schedule(&hc->rh, batch);
     301        }
     302
     303        endpoint_t * const ep = batch->ep;
     304        ehci_endpoint_t * const ehci_ep = ehci_endpoint_get(ep);
    308305        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);
     306
     307        int err;
     308
     309        if ((err = ehci_transfer_batch_prepare(ehci_batch)))
     310                return err;
     311
     312        fibril_mutex_lock(&hc->guard);
     313
     314        if ((err = endpoint_activate_locked(ep, batch))) {
     315                fibril_mutex_unlock(&hc->guard);
     316                return err;
     317        }
     318
     319        usb_log_debug("HC(%p): Committing BATCH(%p)", hc, batch);
    316320        ehci_transfer_batch_commit(ehci_batch);
    317321
    318         fibril_mutex_unlock(&instance->guard);
     322        /* Enqueue endpoint to the checked list */
     323        usb_log_debug2("HC(%p): Appending BATCH(%p)", hc, batch);
     324        list_append(&ehci_ep->pending_link, &hc->pending_endpoints);
     325
     326        fibril_mutex_unlock(&hc->guard);
    319327        return EOK;
    320328}
     
    325333 * @param[in] status Value of the status register at the time of interrupt.
    326334 */
    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);
     335void ehci_hc_interrupt(bus_t *bus_base, uint32_t status)
     336{
     337        assert(bus_base);
     338
     339        ehci_bus_t *bus = (ehci_bus_t *) bus_base;
     340        hc_t *hc = bus->hc;
     341        assert(hc);
     342
     343        usb_log_debug2("HC(%p): Interrupt: %"PRIx32, hc, status);
    335344        if (status & USB_STS_PORT_CHANGE_FLAG) {
    336                 ehci_rh_interrupt(&instance->rh);
     345                ehci_rh_interrupt(&hc->rh);
    337346        }
    338347
    339348        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);
     349                fibril_mutex_lock(&hc->guard);
     350                usb_log_debug2("HC(%p): Signaling doorbell", hc);
     351                fibril_condvar_broadcast(&hc->async_doorbell);
     352                fibril_mutex_unlock(&hc->guard);
    344353        }
    345354
    346355        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)) {
     356                fibril_mutex_lock(&hc->guard);
     357
     358                usb_log_debug2("HC(%p): Scanning %lu pending endpoints", hc,
     359                        list_count(&hc->pending_endpoints));
     360                list_foreach_safe(hc->pending_endpoints, current, next) {
     361                        ehci_endpoint_t *ep
     362                                = list_get_instance(current, ehci_endpoint_t, pending_link);
     363
     364                        ehci_transfer_batch_t *batch
     365                                = ehci_transfer_batch_get(ep->base.active_batch);
     366                        assert(batch);
     367
     368                        if (ehci_transfer_batch_check_completed(batch)) {
     369                                endpoint_deactivate_locked(&ep->base);
    356370                                list_remove(current);
    357                                 ehci_transfer_batch_finish_dispose(batch);
     371                                hc_reset_toggles(&batch->base, &ehci_ep_toggle_reset);
     372                                usb_transfer_batch_finish(&batch->base);
    358373                        }
    359374                }
    360                 fibril_mutex_unlock(&instance->guard);
     375                fibril_mutex_unlock(&hc->guard);
     376
     377
    361378        }
    362379
    363380        if (status & USB_STS_HOST_ERROR_FLAG) {
    364                 usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", instance);
     381                usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", hc);
    365382                //TODO do something here
    366383        }
     
    371388 * @param[in] instance EHCI hc driver structure.
    372389 */
    373 void hc_start(hc_t *instance)
    374 {
    375         assert(instance);
     390int hc_start(hc_device_t *hcd)
     391{
     392        hc_t *instance = hcd_to_hc(hcd);
     393        usb_log_debug("HC(%p): Starting HW.", instance);
     394
    376395        /* Turn off the HC if it's running, Reseting a running device is
    377396         * undefined */
     
    404423
    405424        /* Enable periodic list */
    406         assert(instance->periodic_list_base);
     425        assert(instance->periodic_list);
    407426        uintptr_t phys_base =
    408             addr_to_phys((void*)instance->periodic_list_base);
     427            addr_to_phys((void*)instance->periodic_list);
    409428        assert((phys_base & USB_PERIODIC_LIST_BASE_MASK) == phys_base);
    410429        EHCI_WR(instance->registers->periodiclistbase, phys_base);
     
    425444        usb_log_debug("HC(%p): HW started.", instance);
    426445
    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",
     446        usb_log_debug2("HC(%p): Registers: "
     447            "\tUSBCMD(%p): %x(0x00080000 = at least 1ms between interrupts)"
     448            "\tUSBSTS(%p): %x(0x00001000 = HC halted)"
     449            "\tUSBINT(%p): %x(0x0 = no interrupts)."
     450            "\tCONFIG(%p): %x(0x0 = ports controlled by companion hc).",
    432451            instance,
    433452            &instance->registers->usbcmd, EHCI_RD(instance->registers->usbcmd),
     
    438457        EHCI_WR(instance->registers->usbsts, EHCI_RD(instance->registers->usbsts));
    439458        EHCI_WR(instance->registers->usbintr, EHCI_USED_INTERRUPTS);
     459
     460        return EOK;
     461}
     462
     463/**
     464 * Setup roothub as a virtual hub.
     465 */
     466int hc_setup_roothub(hc_device_t *hcd)
     467{
     468        return hc_setup_virtual_root_hub(hcd, USB_SPEED_HIGH);
    440469}
    441470
     
    473502
    474503        /* Take 1024 periodic list heads, we ignore low mem options */
    475         instance->periodic_list_base = get_page();
    476         if (!instance->periodic_list_base) {
     504        if (dma_buffer_alloc(&instance->dma_buffer, PAGE_SIZE)) {
    477505                usb_log_error("HC(%p): Failed to get ISO schedule page.",
    478506                    instance);
     
    481509                return ENOMEM;
    482510        }
     511        instance->periodic_list = instance->dma_buffer.virt;
    483512
    484513        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)
     514        for (unsigned i = 0; i < PAGE_SIZE/sizeof(link_pointer_t); ++i)
    487515        {
    488516                /* Disable everything for now */
    489                 instance->periodic_list_base[i] =
     517                instance->periodic_list[i] =
    490518                    LINK_POINTER_QH(addr_to_phys(instance->int_list.list_head));
    491519        }
Note: See TracChangeset for help on using the changeset viewer.