Ignore:
File:
1 edited

Legend:

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

    rddbd088 r68e5406  
    4545#include <usb/debug.h>
    4646#include <usb/usb.h>
    47 #include <usb/host/utility.h>
     47#include <usb/host/utils/malloc32.h>
    4848
    4949#include "ehci_batch.h"
     
    8989};
    9090
     91static void hc_start(hc_t *instance);
    9192static int hc_init_memory(hc_t *instance);
    9293
     
    9596 * @param[in] hw_res Device's resources.
    9697 *
     98 * @param[out] irq
     99 *
    97100 * @return Error code.
    98101 */
    99 int hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
     102int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res, int *irq)
    100103{
    101104        assert(code);
    102105        assert(hw_res);
    103         hc_t *instance = hcd_to_hc(hcd);
    104106
    105107        if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1)
     
    128130
    129131        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        }
    130140
    131141        ehci_regs_t *registers =
    132                 (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(instance->caps->caplength));
     142            (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(caps->caplength));
    133143        code->cmds[0].addr = (void *) &registers->usbsts;
    134144        code->cmds[3].addr = (void *) &registers->usbsts;
    135145        EHCI_WR(code->cmds[1].value, EHCI_USED_INTERRUPTS);
    136146
    137         usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.",
     147        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
    138148            RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]);
    139149
    140         return hw_res->irqs.irqs[0];
     150        *irq = hw_res->irqs.irqs[0];
     151        return EOK;
    141152}
    142153
     
    148159 * @return Error code
    149160 */
    150 int hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
    151 {
    152         hc_t *instance = hcd_to_hc(hcd);
     161int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
     162{
     163        assert(instance);
    153164        assert(hw_res);
    154165        if (hw_res->mem_ranges.count != 1 ||
     
    161172        if (ret != EOK) {
    162173                usb_log_error("HC(%p): Failed to gain access to device "
    163                     "registers: %s.", instance, str_error(ret));
     174                    "registers: %s.\n", instance, str_error(ret));
    164175                return ret;
    165176        }
    166 
    167177        usb_log_info("HC(%p): Device registers at %"PRIx64" (%zuB) accessible.",
    168178            instance, hw_res->mem_ranges.ranges[0].address.absolute,
     
    174184            + EHCI_RD8(instance->caps->caplength));
    175185
    176         list_initialize(&instance->pending_endpoints);
     186        list_initialize(&instance->pending_batches);
    177187        fibril_mutex_initialize(&instance->guard);
    178188        fibril_condvar_initialize(&instance->async_doorbell);
     
    187197        usb_log_info("HC(%p): Initializing RH(%p).", instance, &instance->rh);
    188198        ehci_rh_init(
    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);
     199            &instance->rh, instance->caps, instance->registers, "ehci rh");
     200        usb_log_debug("HC(%p): Starting HW.", instance);
     201        hc_start(instance);
     202
    194203        return EOK;
    195204}
     
    199208 * @param[in] instance Host controller structure to use.
    200209 */
    201 int 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;
     210void 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
    208219};
    209220
     
    213224        assert(ep);
    214225        ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep);
    215         usb_log_debug("HC(%p) enqueue EP(%d:%d:%s:%s)", instance,
    216             ep->device->address, ep->endpoint,
     226        usb_log_debug("HC(%p) enqueue EP(%d:%d:%s:%s)\n", instance,
     227            ep->address, ep->endpoint,
    217228            usb_str_transfer_type_short(ep->transfer_type),
    218229            usb_str_direction(ep->direction));
     
    237248        assert(ep);
    238249        ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep);
    239         usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s)", instance,
    240             ep->device->address, ep->endpoint,
     250        usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s)\n", instance,
     251            ep->address, ep->endpoint,
    241252            usb_str_transfer_type_short(ep->transfer_type),
    242253            usb_str_direction(ep->direction));
     
    262273}
    263274
    264 int ehci_hc_status(bus_t *bus_base, uint32_t *status)
    265 {
    266         assert(bus_base);
     275int 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);
    267280        assert(status);
    268 
    269         ehci_bus_t *bus = (ehci_bus_t *) bus_base;
    270         hc_t *hc = bus->hc;
    271         assert(hc);
    272 
    273281        *status = 0;
    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);
     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);
    279287        return EOK;
    280288}
     
    286294 * @return Error code.
    287295 */
    288 int 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);
     296int 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);
    295301
    296302        /* Check for root hub communication */
    297         if (batch->target.address == ehci_rh_get_address(&hc->rh)) {
     303        if (batch->ep->address == ehci_rh_get_address(&instance->rh)) {
    298304                usb_log_debug("HC(%p): Scheduling BATCH(%p) for RH(%p)",
    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);
     305                    instance, batch, &instance->rh);
     306                return ehci_rh_schedule(&instance->rh, batch);
     307        }
    305308        ehci_transfer_batch_t *ehci_batch = ehci_transfer_batch_get(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);
     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);
    320316        ehci_transfer_batch_commit(ehci_batch);
    321317
    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);
     318        fibril_mutex_unlock(&instance->guard);
    327319        return EOK;
    328320}
     
    333325 * @param[in] status Value of the status register at the time of interrupt.
    334326 */
    335 void 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);
     327void 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);
    344335        if (status & USB_STS_PORT_CHANGE_FLAG) {
    345                 ehci_rh_interrupt(&hc->rh);
     336                ehci_rh_interrupt(&instance->rh);
    346337        }
    347338
    348339        if (status & USB_STS_IRQ_ASYNC_ADVANCE_FLAG) {
    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);
     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);
    353344        }
    354345
    355346        if (status & (USB_STS_IRQ_FLAG | USB_STS_ERR_IRQ_FLAG)) {
    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);
     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)) {
    370356                                list_remove(current);
    371                                 hc_reset_toggles(&batch->base, &ehci_ep_toggle_reset);
    372                                 usb_transfer_batch_finish(&batch->base);
     357                                ehci_transfer_batch_finish_dispose(batch);
    373358                        }
    374359                }
    375                 fibril_mutex_unlock(&hc->guard);
    376 
    377 
     360                fibril_mutex_unlock(&instance->guard);
    378361        }
    379362
    380363        if (status & USB_STS_HOST_ERROR_FLAG) {
    381                 usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", hc);
     364                usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", instance);
    382365                //TODO do something here
    383366        }
     
    388371 * @param[in] instance EHCI hc driver structure.
    389372 */
    390 int 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 
     373void hc_start(hc_t *instance)
     374{
     375        assert(instance);
    395376        /* Turn off the HC if it's running, Reseting a running device is
    396377         * undefined */
     
    423404
    424405        /* Enable periodic list */
    425         assert(instance->periodic_list);
     406        assert(instance->periodic_list_base);
    426407        uintptr_t phys_base =
    427             addr_to_phys((void*)instance->periodic_list);
     408            addr_to_phys((void*)instance->periodic_list_base);
    428409        assert((phys_base & USB_PERIODIC_LIST_BASE_MASK) == phys_base);
    429410        EHCI_WR(instance->registers->periodiclistbase, phys_base);
     
    444425        usb_log_debug("HC(%p): HW started.", instance);
    445426
    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).",
     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",
    451432            instance,
    452433            &instance->registers->usbcmd, EHCI_RD(instance->registers->usbcmd),
     
    457438        EHCI_WR(instance->registers->usbsts, EHCI_RD(instance->registers->usbsts));
    458439        EHCI_WR(instance->registers->usbintr, EHCI_USED_INTERRUPTS);
    459 
    460         return EOK;
    461 }
    462 
    463 /**
    464  * Setup roothub as a virtual hub.
    465  */
    466 int hc_setup_roothub(hc_device_t *hcd)
    467 {
    468         return hc_setup_virtual_root_hub(hcd, USB_SPEED_HIGH);
    469440}
    470441
     
    502473
    503474        /* Take 1024 periodic list heads, we ignore low mem options */
    504         if (dma_buffer_alloc(&instance->dma_buffer, PAGE_SIZE)) {
     475        instance->periodic_list_base = get_page();
     476        if (!instance->periodic_list_base) {
    505477                usb_log_error("HC(%p): Failed to get ISO schedule page.",
    506478                    instance);
     
    509481                return ENOMEM;
    510482        }
    511         instance->periodic_list = instance->dma_buffer.virt;
    512483
    513484        usb_log_debug2("HC(%p): Initializing Periodic list.", instance);
    514         for (unsigned i = 0; i < PAGE_SIZE/sizeof(link_pointer_t); ++i)
     485        for (unsigned i = 0;
     486            i < PAGE_SIZE/sizeof(instance->periodic_list_base[0]); ++i)
    515487        {
    516488                /* Disable everything for now */
    517                 instance->periodic_list[i] =
     489                instance->periodic_list_base[i] =
    518490                    LINK_POINTER_QH(addr_to_phys(instance->int_list.list_head));
    519491        }
Note: See TracChangeset for help on using the changeset viewer.