Ignore:
File:
1 edited

Legend:

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

    r5a6cc679 rb7fd2a0  
    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 errno_t hc_init_memory(hc_t *instance);
    9293
     
    99100 * @return Error code.
    100101 */
    101 errno_t hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res, int *irq)
     102errno_t ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res, int *irq)
    102103{
    103104        assert(code);
    104105        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        }
    132140
    133141        ehci_regs_t *registers =
    134                 (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(instance->caps->caplength));
     142            (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(caps->caplength));
    135143        code->cmds[0].addr = (void *) &registers->usbsts;
    136144        code->cmds[3].addr = (void *) &registers->usbsts;
    137145        EHCI_WR(code->cmds[1].value, EHCI_USED_INTERRUPTS);
    138146
    139         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",
    140148            RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]);
    141149
     
    151159 * @return Error code
    152160 */
    153 errno_t hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
    154 {
    155         hc_t *instance = hcd_to_hc(hcd);
     161errno_t hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
     162{
     163        assert(instance);
    156164        assert(hw_res);
    157165        if (hw_res->mem_ranges.count != 1 ||
     
    164172        if (ret != EOK) {
    165173                usb_log_error("HC(%p): Failed to gain access to device "
    166                     "registers: %s.", instance, str_error(ret));
     174                    "registers: %s.\n", instance, str_error(ret));
    167175                return ret;
    168176        }
    169 
    170177        usb_log_info("HC(%p): Device registers at %"PRIx64" (%zuB) accessible.",
    171178            instance, hw_res->mem_ranges.ranges[0].address.absolute,
     
    177184            + EHCI_RD8(instance->caps->caplength));
    178185
    179         list_initialize(&instance->pending_endpoints);
     186        list_initialize(&instance->pending_batches);
    180187        fibril_mutex_initialize(&instance->guard);
    181188        fibril_condvar_initialize(&instance->async_doorbell);
     
    190197        usb_log_info("HC(%p): Initializing RH(%p).", instance, &instance->rh);
    191198        ehci_rh_init(
    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);
     199            &instance->rh, instance->caps, instance->registers, "ehci rh");
     200        usb_log_debug("HC(%p): Starting HW.", instance);
     201        hc_start(instance);
     202
    197203        return EOK;
    198204}
     
    202208 * @param[in] instance Host controller structure to use.
    203209 */
    204 int 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;
     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
    211219};
    212220
     
    216224        assert(ep);
    217225        ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep);
    218         usb_log_debug("HC(%p) enqueue EP(%d:%d:%s:%s)", instance,
    219             ep->device->address, ep->endpoint,
     226        usb_log_debug("HC(%p) enqueue EP(%d:%d:%s:%s)\n", instance,
     227            ep->address, ep->endpoint,
    220228            usb_str_transfer_type_short(ep->transfer_type),
    221229            usb_str_direction(ep->direction));
     
    240248        assert(ep);
    241249        ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep);
    242         usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s)", instance,
    243             ep->device->address, ep->endpoint,
     250        usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s)\n", instance,
     251            ep->address, ep->endpoint,
    244252            usb_str_transfer_type_short(ep->transfer_type),
    245253            usb_str_direction(ep->direction));
     
    265273}
    266274
    267 errno_t ehci_hc_status(bus_t *bus_base, uint32_t *status)
    268 {
    269         assert(bus_base);
     275errno_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);
    270280        assert(status);
    271 
    272         ehci_bus_t *bus = (ehci_bus_t *) bus_base;
    273         hc_t *hc = bus->hc;
    274         assert(hc);
    275 
    276281        *status = 0;
    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);
     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);
    282287        return EOK;
    283288}
     
    289294 * @return Error code.
    290295 */
    291 errno_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);
     296errno_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);
    298301
    299302        /* Check for root hub communication */
    300         if (batch->target.address == ehci_rh_get_address(&hc->rh)) {
     303        if (batch->ep->address == ehci_rh_get_address(&instance->rh)) {
    301304                usb_log_debug("HC(%p): Scheduling BATCH(%p) for RH(%p)",
    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);
     305                    instance, batch, &instance->rh);
     306                return ehci_rh_schedule(&instance->rh, batch);
     307        }
    308308        ehci_transfer_batch_t *ehci_batch = ehci_transfer_batch_get(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);
     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);
    323316        ehci_transfer_batch_commit(ehci_batch);
    324317
    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);
     318        fibril_mutex_unlock(&instance->guard);
    330319        return EOK;
    331320}
     
    336325 * @param[in] status Value of the status register at the time of interrupt.
    337326 */
    338 void 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);
     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);
    347335        if (status & USB_STS_PORT_CHANGE_FLAG) {
    348                 ehci_rh_interrupt(&hc->rh);
     336                ehci_rh_interrupt(&instance->rh);
    349337        }
    350338
    351339        if (status & USB_STS_IRQ_ASYNC_ADVANCE_FLAG) {
    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);
     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);
    356344        }
    357345
    358346        if (status & (USB_STS_IRQ_FLAG | USB_STS_ERR_IRQ_FLAG)) {
    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);
     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)) {
    373356                                list_remove(current);
    374                                 hc_reset_toggles(&batch->base, &ehci_ep_toggle_reset);
    375                                 usb_transfer_batch_finish(&batch->base);
     357                                ehci_transfer_batch_finish_dispose(batch);
    376358                        }
    377359                }
    378                 fibril_mutex_unlock(&hc->guard);
    379 
    380 
     360                fibril_mutex_unlock(&instance->guard);
    381361        }
    382362
    383363        if (status & USB_STS_HOST_ERROR_FLAG) {
    384                 usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", hc);
     364                usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", instance);
    385365                //TODO do something here
    386366        }
     
    391371 * @param[in] instance EHCI hc driver structure.
    392372 */
    393 int 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 
     373void hc_start(hc_t *instance)
     374{
     375        assert(instance);
    398376        /* Turn off the HC if it's running, Reseting a running device is
    399377         * undefined */
     
    426404
    427405        /* Enable periodic list */
    428         assert(instance->periodic_list);
     406        assert(instance->periodic_list_base);
    429407        uintptr_t phys_base =
    430             addr_to_phys((void*)instance->periodic_list);
     408            addr_to_phys((void*)instance->periodic_list_base);
    431409        assert((phys_base & USB_PERIODIC_LIST_BASE_MASK) == phys_base);
    432410        EHCI_WR(instance->registers->periodiclistbase, phys_base);
     
    447425        usb_log_debug("HC(%p): HW started.", instance);
    448426
    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).",
     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",
    454432            instance,
    455433            &instance->registers->usbcmd, EHCI_RD(instance->registers->usbcmd),
     
    460438        EHCI_WR(instance->registers->usbsts, EHCI_RD(instance->registers->usbsts));
    461439        EHCI_WR(instance->registers->usbintr, EHCI_USED_INTERRUPTS);
    462 
    463         return EOK;
    464 }
    465 
    466 /**
    467  * Setup roothub as a virtual hub.
    468  */
    469 int hc_setup_roothub(hc_device_t *hcd)
    470 {
    471         return hc_setup_virtual_root_hub(hcd, USB_SPEED_HIGH);
    472440}
    473441
     
    505473
    506474        /* Take 1024 periodic list heads, we ignore low mem options */
    507         if (dma_buffer_alloc(&instance->dma_buffer, PAGE_SIZE)) {
     475        instance->periodic_list_base = get_page();
     476        if (!instance->periodic_list_base) {
    508477                usb_log_error("HC(%p): Failed to get ISO schedule page.",
    509478                    instance);
     
    512481                return ENOMEM;
    513482        }
    514         instance->periodic_list = instance->dma_buffer.virt;
    515483
    516484        usb_log_debug2("HC(%p): Initializing Periodic list.", instance);
    517         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)
    518487        {
    519488                /* Disable everything for now */
    520                 instance->periodic_list[i] =
     489                instance->periodic_list_base[i] =
    521490                    LINK_POINTER_QH(addr_to_phys(instance->int_list.list_head));
    522491        }
Note: See TracChangeset for help on using the changeset viewer.