Ignore:
File:
1 edited

Legend:

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

    r795448f rc53007f  
    3333 * @brief UHCI driver
    3434 */
     35
     36/* XXX Fix this */
     37#define _DDF_DATA_IMPLANT
     38
    3539#include <errno.h>
     40#include <stdbool.h>
    3641#include <str_error.h>
    3742#include <ddf/interrupt.h>
     
    6065} uhci_t;
    6166
    62 static inline uhci_t * dev_to_uhci(const ddf_dev_t *dev)
    63 {
    64         assert(dev);
    65         return dev->driver_data;
    66 }
    67 /*----------------------------------------------------------------------------*/
     67static inline uhci_t *dev_to_uhci(ddf_dev_t *dev)
     68{
     69        return ddf_dev_data_get(dev);
     70}
     71
    6872/** IRQ handling callback, forward status from call to diver structure.
    6973 *
     
    8387        hc_interrupt(&uhci->hc, status);
    8488}
    85 /*----------------------------------------------------------------------------*/
     89
    8690/** Operations supported by the HC driver */
    8791static ddf_dev_ops_t hc_ops = {
    8892        .interfaces[USBHC_DEV_IFACE] = &hcd_iface, /* see iface.h/c */
    8993};
    90 /*----------------------------------------------------------------------------*/
     94
    9195/** Gets handle of the respective hc.
    9296 *
     
    97101static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
    98102{
    99         assert(fun);
    100         ddf_fun_t *hc_fun = dev_to_uhci(fun->dev)->hc_fun;
     103        ddf_fun_t *hc_fun = dev_to_uhci(ddf_fun_get_dev(fun))->hc_fun;
    101104        assert(hc_fun);
    102105
    103106        if (handle != NULL)
    104                 *handle = hc_fun->handle;
     107                *handle = ddf_fun_get_handle(hc_fun);
    105108        return EOK;
    106109}
    107 /*----------------------------------------------------------------------------*/
     110
    108111/** USB interface implementation used by RH */
    109112static usb_iface_t usb_iface = {
    110113        .get_hc_handle = usb_iface_get_hc_handle,
    111114};
    112 /*----------------------------------------------------------------------------*/
     115
    113116/** Get root hub hw resources (I/O registers).
    114117 *
     
    118121static hw_resource_list_t *get_resource_list(ddf_fun_t *fun)
    119122{
    120         assert(fun);
    121         rh_t *rh = fun->driver_data;
     123        rh_t *rh = ddf_fun_data_get(fun);
    122124        assert(rh);
    123125        return &rh->resource_list;
    124126}
    125 /*----------------------------------------------------------------------------*/
     127
    126128/** Interface to provide the root hub driver with hw info */
    127129static hw_res_ops_t hw_res_iface = {
     
    129131        .enable_interrupt = NULL,
    130132};
    131 /*----------------------------------------------------------------------------*/
     133
    132134/** RH function support for uhci_rhd */
    133135static ddf_dev_ops_t rh_ops = {
     
    135137        .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface
    136138};
    137 /*----------------------------------------------------------------------------*/
     139
    138140/** Initialize hc and rh DDF structures and their respective drivers.
    139141 *
     
    148150int device_setup_uhci(ddf_dev_t *device)
    149151{
     152        bool ih_registered = false;
     153        bool hc_inited = false;
     154        bool fun_bound = false;
     155        int rc;
     156
    150157        if (!device)
    151158                return EBADMEM;
     
    157164        }
    158165
    159 #define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
    160 if (ret != EOK) { \
    161         if (instance->hc_fun) \
    162                 instance->hc_fun->driver_data = NULL; \
    163                 ddf_fun_destroy(instance->hc_fun); \
    164         if (instance->rh_fun) {\
    165                 instance->rh_fun->driver_data = NULL; \
    166                 ddf_fun_destroy(instance->rh_fun); \
    167         } \
    168         usb_log_error(message); \
    169         return ret; \
    170 } else (void)0
    171 
    172         instance->rh_fun = NULL;
    173166        instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci_hc");
    174         int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
    175         CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n");
    176         instance->hc_fun->ops = &hc_ops;
    177         instance->hc_fun->driver_data = &instance->hc.generic;
     167        if (instance->hc_fun == NULL) {
     168                usb_log_error("Failed to create UHCI HC function.\n");
     169                rc = ENOMEM;
     170                goto error;
     171        }
     172
     173        ddf_fun_set_ops(instance->hc_fun, &hc_ops);
     174        ddf_fun_data_implant(instance->hc_fun, &instance->hc.generic);
    178175
    179176        instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh");
    180         ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
    181         CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n");
    182         instance->rh_fun->ops = &rh_ops;
    183         instance->rh_fun->driver_data = &instance->rh;
     177        if (instance->rh_fun == NULL) {
     178                usb_log_error("Failed to create UHCI RH function.\n");
     179                rc = ENOMEM;
     180                goto error;
     181        }
     182
     183        ddf_fun_set_ops(instance->rh_fun, &rh_ops);
     184        ddf_fun_data_implant(instance->rh_fun, &instance->rh);
    184185
    185186        uintptr_t reg_base = 0;
     
    187188        int irq = 0;
    188189
    189         ret = get_my_registers(device, &reg_base, &reg_size, &irq);
    190         CHECK_RET_DEST_FREE_RETURN(ret,
    191             "Failed to get I/O addresses for %" PRIun ": %s.\n",
    192             device->handle, str_error(ret));
     190        rc = get_my_registers(device, &reg_base, &reg_size, &irq);
     191        if (rc != EOK) {
     192                usb_log_error("Failed to get I/O addresses for %" PRIun ": %s.\n",
     193                    ddf_dev_get_handle(device), str_error(rc));
     194                goto error;
     195        }
    193196        usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n",
    194197            (void *) reg_base, reg_size, irq);
    195198
    196         ret = disable_legacy(device);
    197         CHECK_RET_DEST_FREE_RETURN(ret,
    198             "Failed to disable legacy USB: %s.\n", str_error(ret));
    199 
    200         const size_t ranges_count = hc_irq_pio_range_count();
    201         const size_t cmds_count = hc_irq_cmd_count();
    202         irq_pio_range_t irq_ranges[ranges_count];
    203         irq_cmd_t irq_cmds[cmds_count];
    204         ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
    205             sizeof(irq_cmds), reg_base, reg_size);
    206         CHECK_RET_DEST_FREE_RETURN(ret,
    207             "Failed to generate IRQ commands: %s.\n", str_error(ret));
    208 
    209         irq_code_t irq_code = {
    210                 .rangecount = ranges_count,
    211                 .ranges = irq_ranges,
    212                 .cmdcount = cmds_count,
    213                 .cmds = irq_cmds
    214         };
    215 
    216         /* Register handler to avoid interrupt lockup */
    217         ret = register_interrupt_handler(device, irq, irq_handler, &irq_code);
    218         CHECK_RET_DEST_FREE_RETURN(ret,
    219             "Failed to register interrupt handler: %s.\n", str_error(ret));
     199        rc = disable_legacy(device);
     200        if (rc != EOK) {
     201                usb_log_error("Failed to disable legacy USB: %s.\n",
     202                    str_error(rc));
     203                goto error;
     204        }
     205
     206        rc = hc_register_irq_handler(device, reg_base, reg_size, irq, irq_handler);
     207        if (rc != EOK) {
     208                usb_log_error("Failed to register interrupt handler: %s.\n",
     209                    str_error(rc));
     210                goto error;
     211        }
     212
     213        ih_registered = true;
    220214
    221215        bool interrupts = false;
    222         ret = enable_interrupts(device);
    223         if (ret != EOK) {
     216        rc = enable_interrupts(device);
     217        if (rc != EOK) {
    224218                usb_log_warning("Failed to enable interrupts: %s."
    225                     " Falling back to polling.\n", str_error(ret));
     219                    " Falling back to polling.\n", str_error(rc));
    226220        } else {
    227221                usb_log_debug("Hw interrupts enabled.\n");
     
    229223        }
    230224
    231         ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
    232         CHECK_RET_DEST_FREE_RETURN(ret,
    233             "Failed to init uhci_hcd: %s.\n", str_error(ret));
    234 
    235 #define CHECK_RET_FINI_RETURN(ret, message...) \
    236 if (ret != EOK) { \
    237         hc_fini(&instance->hc); \
    238         CHECK_RET_DEST_FREE_RETURN(ret, message); \
    239         return ret; \
    240 } else (void)0
    241 
    242         ret = ddf_fun_bind(instance->hc_fun);
    243         CHECK_RET_FINI_RETURN(ret, "Failed to bind UHCI device function: %s.\n",
    244             str_error(ret));
    245 
    246         ret = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY);
    247         CHECK_RET_FINI_RETURN(ret,
    248             "Failed to add UHCI to HC class: %s.\n", str_error(ret));
    249 
    250         ret = rh_init(&instance->rh, instance->rh_fun,
     225        rc = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
     226        if (rc != EOK) {
     227                usb_log_error("Failed to init uhci_hcd: %s.\n", str_error(rc));
     228                goto error;
     229        }
     230
     231        hc_inited = true;
     232
     233        rc = ddf_fun_bind(instance->hc_fun);
     234        if (rc != EOK) {
     235                usb_log_error("Failed to bind UHCI device function: %s.\n",
     236                    str_error(rc));
     237                goto error;
     238        }
     239
     240        fun_bound = true;
     241
     242        rc = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY);
     243        if (rc != EOK) {
     244                usb_log_error("Failed to add UHCI to HC class: %s.\n",
     245                    str_error(rc));
     246                goto error;
     247        }
     248
     249        rc = rh_init(&instance->rh, instance->rh_fun,
    251250            (uintptr_t)instance->hc.registers + 0x10, 4);
    252         CHECK_RET_FINI_RETURN(ret,
    253             "Failed to setup UHCI root hub: %s.\n", str_error(ret));
    254 
    255         ret = ddf_fun_bind(instance->rh_fun);
    256         CHECK_RET_FINI_RETURN(ret,
    257             "Failed to register UHCI root hub: %s.\n", str_error(ret));
     251        if (rc != EOK) {
     252                usb_log_error("Failed to setup UHCI root hub: %s.\n",
     253                    str_error(rc));
     254                goto error;
     255        }
     256
     257        rc = ddf_fun_bind(instance->rh_fun);
     258        if (rc != EOK) {
     259                usb_log_error("Failed to register UHCI root hub: %s.\n",
     260                    str_error(rc));
     261                goto error;
     262        }
    258263
    259264        return EOK;
    260 #undef CHECK_RET_FINI_RETURN
     265
     266error:
     267        if (fun_bound)
     268                ddf_fun_unbind(instance->hc_fun);
     269        if (hc_inited)
     270                hc_fini(&instance->hc);
     271        if (ih_registered)
     272                unregister_interrupt_handler(device, irq);
     273        if (instance->hc_fun != NULL)
     274                ddf_fun_destroy(instance->hc_fun);
     275        if (instance->rh_fun != NULL) {
     276                ddf_fun_destroy(instance->rh_fun);
     277        }
     278        return rc;
    261279}
    262280/**
Note: See TracChangeset for help on using the changeset viewer.