Changeset e4d7363 in mainline for uspace/lib/usbhost/src/ddf_helpers.c


Ignore:
Timestamp:
2017-06-22T21:34:39Z (7 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
91ca111
Parents:
cb89430
Message:

usbhost: refactor the initialization

Before that, drivers had to setup MMIO range multiple times, or even parse hw
resources themselves again. The former init method was split in half - init and
start. Init shall allocate and initialize inner structures, start shall start
the HC.

In the XHCI it is demonstrated how to isolate inner HC implementation from the
fact this driver is using libusbhost. It adds some boilerplate code, but
I think it leads to cleaner design.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbhost/src/ddf_helpers.c

    rcb89430 re4d7363  
    753753    const hw_res_list_parsed_t *hw_res,
    754754    interrupt_handler_t handler,
    755     int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *hw_res))
    756 {
    757 
     755    irq_code_gen_t gen_irq_code)
     756{
    758757        assert(device);
     758
     759        hcd_t *hcd = dev_to_hcd(device);
     760
    759761        if (!handler || !gen_irq_code)
    760762                return ENOTSUP;
     
    762764        irq_code_t irq_code = {0};
    763765
    764         const int irq = gen_irq_code(&irq_code, hw_res);
     766        const int irq = gen_irq_code(&irq_code, hcd, hw_res);
    765767        if (irq < 0) {
    766768                usb_log_error("Failed to generate IRQ code: %s.\n",
     
    878880        if (ret != EOK) {
    879881                usb_log_error("Failed to setup generic HCD.\n");
    880                 hw_res_list_parsed_clean(&hw_res);
    881                 return ret;
    882         }
    883 
     882                goto err_hw_res;
     883        }
     884
     885        hcd_t *hcd = dev_to_hcd(device);
     886
     887        if (driver->init)
     888                ret = driver->init(hcd, &hw_res);
     889        if (ret != EOK) {
     890                usb_log_error("Failed to init HCD.\n");
     891                goto err_hcd;
     892        }
     893
     894        /* Setup interrupts  */
    884895        interrupt_handler_t *irq_handler =
    885896            driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler;
    886         const int irq = hcd_ddf_setup_interrupts(device, &hw_res, irq_handler,
    887             driver->irq_code_gen);
     897        const int irq = hcd_ddf_setup_interrupts(device, &hw_res, irq_handler, driver->irq_code_gen);
    888898        if (!(irq < 0)) {
    889899                usb_log_debug("Hw interrupts enabled.\n");
    890900        }
    891901
     902        /* Claim the device from BIOS */
    892903        if (driver->claim)
    893                 ret = driver->claim(device);
    894         if (ret != EOK) {
    895                 usb_log_error("Failed to claim `%s' for driver `%s'",
    896                     ddf_dev_get_name(device), driver->name);
    897                 return ret;
    898         }
    899 
    900 
    901         /* Init hw driver */
    902         hcd_t *hcd = dev_to_hcd(device);
    903         ret = driver->init(hcd, &hw_res, !(irq < 0));
    904         hw_res_list_parsed_clean(&hw_res);
    905         if (ret != EOK) {
    906                 usb_log_error("Failed to init HCD: %s.\n", str_error(ret));
    907                 goto irq_unregister;
     904                ret = driver->claim(hcd, device);
     905        if (ret != EOK) {
     906                usb_log_error("Failed to claim `%s' for driver `%s': %s",
     907                    ddf_dev_get_name(device), driver->name, str_error(ret));
     908                goto err_irq;
     909        }
     910
     911        /* Start hw driver */
     912        if (driver->start)
     913                ret = driver->start(hcd, !(irq < 0));
     914        if (ret != EOK) {
     915                usb_log_error("Failed to start HCD: %s.\n", str_error(ret));
     916                goto err_irq;
    908917        }
    909918
     
    914923                        usb_log_error("Failed to create polling fibril\n");
    915924                        ret = ENOMEM;
    916                         goto irq_unregister;
     925                        goto err_started;
    917926                }
    918927                fibril_add_ready(hcd->polling_fibril);
     
    929938                usb_log_error("Failed to setup HC root hub: %s.\n",
    930939                    str_error(ret));
    931                 driver->fini(dev_to_hcd(device));
    932 irq_unregister:
    933                 /* Unregistering non-existent should be ok */
    934                 unregister_interrupt_handler(device, irq);
    935                 hcd_ddf_clean_hc(device);
    936                 return ret;
     940                goto err_polling;
    937941        }
    938942
     
    940944            driver->name, ddf_dev_get_name(device));
    941945        return EOK;
     946       
     947err_polling:
     948        // TODO: Stop the polling fibril (refactor the interrupt_polling func)
     949        //
     950err_started:
     951        if (driver->stop)
     952                driver->stop(hcd);
     953err_irq:
     954        unregister_interrupt_handler(device, irq);
     955        if (driver->fini)
     956                driver->fini(hcd);
     957err_hcd:
     958        hcd_ddf_clean_hc(device);
     959err_hw_res:
     960        hw_res_list_parsed_clean(&hw_res);
     961        return ret;
    942962}
    943963/**
Note: See TracChangeset for help on using the changeset viewer.