Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ohci/ohci.c

    r507c6f3 r44c1a48  
    3333 * @brief OHCI driver
    3434 */
    35 
    36 /* XXX Fix this */
    37 #define _DDF_DATA_IMPLANT
    38 
    3935#include <errno.h>
    4036#include <str_error.h>
     
    5652} ohci_t;
    5753
    58 static inline ohci_t *dev_to_ohci(ddf_dev_t *dev)
    59 {
    60         return ddf_dev_data_get(dev);
     54static inline ohci_t * dev_to_ohci(ddf_dev_t *dev)
     55{
     56        assert(dev);
     57        return dev->driver_data;
    6158}
    6259/** IRQ handling callback, identifies device
     
    7875        hc_interrupt(&ohci->hc, status);
    7976}
    80 
     77/*----------------------------------------------------------------------------*/
    8178/** Get USB address assigned to root hub.
    8279 *
     
    9087
    9188        if (address != NULL) {
    92                 *address = dev_to_ohci(ddf_fun_get_dev(fun))->hc.rh.address;
     89                *address = dev_to_ohci(fun->dev)->hc.rh.address;
    9390        }
    9491
    9592        return EOK;
    9693}
    97 
     94/*----------------------------------------------------------------------------*/
    9895/** Gets handle of the respective hc (this device, hc function).
    9996 *
     
    106103{
    107104        assert(fun);
    108         ddf_fun_t *hc_fun = dev_to_ohci(ddf_fun_get_dev(fun))->hc_fun;
     105        ddf_fun_t *hc_fun = dev_to_ohci(fun->dev)->hc_fun;
    109106        assert(hc_fun);
    110107
    111108        if (handle != NULL)
    112                 *handle = ddf_fun_get_handle(hc_fun);
     109                *handle = hc_fun->handle;
    113110        return EOK;
    114111}
    115 
     112/*----------------------------------------------------------------------------*/
    116113/** Root hub USB interface */
    117114static usb_iface_t usb_iface = {
     
    119116        .get_my_address = rh_get_my_address,
    120117};
    121 
     118/*----------------------------------------------------------------------------*/
    122119/** Standard USB HC options (HC interface) */
    123120static ddf_dev_ops_t hc_ops = {
    124121        .interfaces[USBHC_DEV_IFACE] = &hcd_iface,
    125122};
    126 
     123/*----------------------------------------------------------------------------*/
    127124/** Standard USB RH options (RH interface) */
    128125static ddf_dev_ops_t rh_ops = {
    129126        .interfaces[USB_DEV_IFACE] = &usb_iface,
    130127};
    131 
     128/*----------------------------------------------------------------------------*/
    132129/** Initialize hc and rh ddf structures and their respective drivers.
    133130 *
     
    143140int device_setup_ohci(ddf_dev_t *device)
    144141{
    145         bool ih_registered = false;
    146         bool hc_inited = false;
    147         int rc;
    148 
    149142        if (device == NULL)
    150143                return EBADMEM;
     
    156149        }
    157150
     151#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
     152if (ret != EOK) { \
     153        if (instance->hc_fun) { \
     154                instance->hc_fun->driver_data = NULL; \
     155                ddf_fun_destroy(instance->hc_fun); \
     156        } \
     157        if (instance->rh_fun) { \
     158                instance->rh_fun->driver_data = NULL; \
     159                ddf_fun_destroy(instance->rh_fun); \
     160        } \
     161        usb_log_error(message); \
     162        return ret; \
     163} else (void)0
     164
    158165        instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc");
    159         if (instance->hc_fun == NULL) {
    160                 usb_log_error("Failed to create OHCI HC function: %s.\n",
    161                     str_error(ENOMEM));
    162                 rc = ENOMEM;
    163                 goto error;
    164         }
    165 
    166         ddf_fun_set_ops(instance->hc_fun, &hc_ops);
    167         ddf_fun_data_implant(instance->hc_fun, &instance->hc);
     166        int ret = instance->hc_fun ? EOK : ENOMEM;
     167        CHECK_RET_DEST_FREE_RETURN(ret,
     168            "Failed to create OHCI HC function: %s.\n", str_error(ret));
     169        instance->hc_fun->ops = &hc_ops;
     170        instance->hc_fun->driver_data = &instance->hc;
    168171
    169172        instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh");
    170         if (instance->rh_fun == NULL) {
    171                 usb_log_error("Failed to create OHCI RH function: %s.\n",
    172                     str_error(ENOMEM));
    173                 rc = ENOMEM;
    174                 goto error;
    175         }
    176 
    177         ddf_fun_set_ops(instance->rh_fun, &rh_ops);
     173        ret = instance->rh_fun ? EOK : ENOMEM;
     174        CHECK_RET_DEST_FREE_RETURN(ret,
     175            "Failed to create OHCI RH function: %s.\n", str_error(ret));
     176        instance->rh_fun->ops = &rh_ops;
    178177
    179178        uintptr_t reg_base = 0;
     
    181180        int irq = 0;
    182181
    183         rc = get_my_registers(device, &reg_base, &reg_size, &irq);
    184         if (rc != EOK) {
    185                 usb_log_error("Failed to get register memory addresses "
    186                     "for %" PRIun ": %s.\n", ddf_dev_get_handle(device),
    187                     str_error(rc));
    188                 goto error;
    189         }
    190 
     182        ret = get_my_registers(device, &reg_base, &reg_size, &irq);
     183        CHECK_RET_DEST_FREE_RETURN(ret,
     184            "Failed to get register memory addresses for %" PRIun ": %s.\n",
     185            device->handle, str_error(ret));
    191186        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
    192187            (void *) reg_base, reg_size, irq);
    193188
    194         rc = hc_register_irq_handler(device, reg_base, reg_size, irq, irq_handler);
    195         if (rc != EOK) {
    196                 usb_log_error("Failed to register interrupt handler: %s.\n",
    197                     str_error(rc));
    198                 goto error;
    199         }
    200 
    201         ih_registered = true;
     189        const size_t ranges_count = hc_irq_pio_range_count();
     190        const size_t cmds_count = hc_irq_cmd_count();
     191        irq_pio_range_t irq_ranges[ranges_count];
     192        irq_cmd_t irq_cmds[cmds_count];
     193        irq_code_t irq_code = {
     194                .rangecount = ranges_count,
     195                .ranges = irq_ranges,
     196                .cmdcount = cmds_count,
     197                .cmds = irq_cmds
     198        };
     199
     200        ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
     201            sizeof(irq_cmds), reg_base, reg_size);
     202        CHECK_RET_DEST_FREE_RETURN(ret,
     203            "Failed to generate IRQ code: %s.\n", str_error(ret));
     204
     205
     206        /* Register handler to avoid interrupt lockup */
     207        ret = register_interrupt_handler(device, irq, irq_handler, &irq_code);
     208        CHECK_RET_DEST_FREE_RETURN(ret,
     209            "Failed to register interrupt handler: %s.\n", str_error(ret));
    202210
    203211        /* Try to enable interrupts */
    204212        bool interrupts = false;
    205         rc = enable_interrupts(device);
    206         if (rc != EOK) {
     213        ret = enable_interrupts(device);
     214        if (ret != EOK) {
    207215                usb_log_warning("Failed to enable interrupts: %s."
    208                     " Falling back to polling\n", str_error(rc));
     216                    " Falling back to polling\n", str_error(ret));
    209217                /* We don't need that handler */
    210218                unregister_interrupt_handler(device, irq);
    211                 ih_registered = false;
    212219        } else {
    213220                usb_log_debug("Hw interrupts enabled.\n");
     
    215222        }
    216223
    217         rc = hc_init(&instance->hc, reg_base, reg_size, interrupts);
    218         if (rc != EOK) {
    219                 usb_log_error("Failed to init ohci_hcd: %s.\n", str_error(rc));
    220                 goto error;
    221         }
    222 
    223         hc_inited = true;
    224 
    225         rc = ddf_fun_bind(instance->hc_fun);
    226         if (rc != EOK) {
    227                 usb_log_error("Failed to bind OHCI device function: %s.\n",
    228                     str_error(rc));
    229                 goto error;
    230         }
    231 
    232         rc = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY);
    233         if (rc != EOK) {
    234                 usb_log_error("Failed to add OHCI to HC category: %s.\n",
    235                     str_error(rc));
    236                 goto error;
    237         }
    238 
    239         rc = hc_register_hub(&instance->hc, instance->rh_fun);
    240         if (rc != EOK) {
    241                 usb_log_error("Failed to register OHCI root hub: %s.\n",
    242                     str_error(rc));
    243                 goto error;
    244         }
    245 
    246         return EOK;
    247 
    248 error:
    249         if (hc_inited)
    250                 hc_fini(&instance->hc);
    251         if (ih_registered)
    252                 unregister_interrupt_handler(device, irq);
    253         if (instance->hc_fun != NULL)
    254                 ddf_fun_destroy(instance->hc_fun);
    255         if (instance->rh_fun != NULL)
    256                 ddf_fun_destroy(instance->rh_fun);
    257         return rc;
     224        ret = hc_init(&instance->hc, reg_base, reg_size, interrupts);
     225        CHECK_RET_DEST_FREE_RETURN(ret,
     226            "Failed to init ohci_hcd: %s.\n", str_error(ret));
     227
     228#define CHECK_RET_FINI_RETURN(ret, message...) \
     229if (ret != EOK) { \
     230        hc_fini(&instance->hc); \
     231        unregister_interrupt_handler(device, irq); \
     232        CHECK_RET_DEST_FREE_RETURN(ret, message); \
     233} else (void)0
     234
     235
     236        ret = ddf_fun_bind(instance->hc_fun);
     237        CHECK_RET_FINI_RETURN(ret,
     238            "Failed to bind OHCI device function: %s.\n", str_error(ret));
     239
     240        ret = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY);
     241        CHECK_RET_FINI_RETURN(ret,
     242            "Failed to add OHCI to HC class: %s.\n", str_error(ret));
     243
     244        ret = hc_register_hub(&instance->hc, instance->rh_fun);
     245        CHECK_RET_FINI_RETURN(ret,
     246            "Failed to register OHCI root hub: %s.\n", str_error(ret));
     247        return ret;
     248
     249#undef CHECK_RET_FINI_RETURN
    258250}
    259251/**
Note: See TracChangeset for help on using the changeset viewer.