Ignore:
File:
1 edited

Legend:

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

    r7de1988c re991937  
    3434 */
    3535
    36 /* XXX Fix this */
    37 #define _DDF_DATA_IMPLANT
    38 
    3936#include <errno.h>
    4037#include <str_error.h>
    4138#include <ddf/interrupt.h>
    42 #include <usb_iface.h>
    4339#include <usb/usb.h>
    44 #include <usb/ddfiface.h>
    4540#include <usb/debug.h>
     41
     42#include <usb/host/ddf_helpers.h>
    4643
    4744#include "ohci.h"
     
    4946#include "hc.h"
    5047
    51 typedef struct ohci {
    52         ddf_fun_t *hc_fun;
    53         ddf_fun_t *rh_fun;
    5448
    55         hc_t hc;
    56 } ohci_t;
    5749
    58 static inline ohci_t *dev_to_ohci(ddf_dev_t *dev)
    59 {
    60         return ddf_dev_data_get(dev);
    61 }
    6250/** IRQ handling callback, identifies device
    6351 *
     
    6957{
    7058        assert(dev);
    71 
    72         ohci_t *ohci = dev_to_ohci(dev);
    73         if (!ohci) {
     59        hcd_t *hcd = dev_to_hcd(dev);
     60        if (!hcd || !hcd->private_data) {
    7461                usb_log_warning("Interrupt on device that is not ready.\n");
    7562                return;
    7663        }
     64
    7765        const uint16_t status = IPC_GET_ARG1(*call);
    78         hc_interrupt(&ohci->hc, status);
     66        hc_interrupt(hcd->private_data, status);
    7967}
    80 
    81 /** Get USB address assigned to root hub.
    82  *
    83  * @param[in] fun Root hub function.
    84  * @param[out] address Store the address here.
    85  * @return Error code.
    86  */
    87 static int rh_get_my_address(ddf_fun_t *fun, usb_address_t *address)
    88 {
    89         assert(fun);
    90 
    91         if (address != NULL) {
    92                 *address = dev_to_ohci(ddf_fun_get_dev(fun))->hc.rh.address;
    93         }
    94 
    95         return EOK;
    96 }
    97 
    98 /** Gets handle of the respective hc (this device, hc function).
    99  *
    100  * @param[in] root_hub_fun Root hub function seeking hc handle.
    101  * @param[out] handle Place to write the handle.
    102  * @return Error code.
    103  */
    104 static int rh_get_hc_handle(
    105     ddf_fun_t *fun, devman_handle_t *handle)
    106 {
    107         assert(fun);
    108         ddf_fun_t *hc_fun = dev_to_ohci(ddf_fun_get_dev(fun))->hc_fun;
    109         assert(hc_fun);
    110 
    111         if (handle != NULL)
    112                 *handle = ddf_fun_get_handle(hc_fun);
    113         return EOK;
    114 }
    115 
    116 /** Root hub USB interface */
    117 static usb_iface_t usb_iface = {
    118         .get_hc_handle = rh_get_hc_handle,
    119         .get_my_address = rh_get_my_address,
    120 };
    121 
    122 /** Standard USB HC options (HC interface) */
    123 static ddf_dev_ops_t hc_ops = {
    124         .interfaces[USBHC_DEV_IFACE] = &hcd_iface,
    125 };
    126 
    127 /** Standard USB RH options (RH interface) */
    128 static ddf_dev_ops_t rh_ops = {
    129         .interfaces[USB_DEV_IFACE] = &usb_iface,
    130 };
    13168
    13269/** Initialize hc and rh ddf structures and their respective drivers.
     
    14380int device_setup_ohci(ddf_dev_t *device)
    14481{
    145         bool ih_registered = false;
    146         bool hc_inited = false;
    147         int rc;
     82#define CHECK_RET_RETURN(ret, message...) \
     83if (ret != EOK) { \
     84        usb_log_error(message); \
     85        return ret; \
     86}
    14887
    149         if (device == NULL)
    150                 return EBADMEM;
    151 
    152         ohci_t *instance = ddf_dev_data_alloc(device,sizeof(ohci_t));
    153         if (instance == NULL) {
    154                 usb_log_error("Failed to allocate OHCI driver.\n");
    155                 return ENOMEM;
    156         }
    157 
    158         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);
    168 
    169         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);
    178 
    179         addr_range_t regs;
     88        uintptr_t reg_base = 0;
     89        size_t reg_size = 0;
    18090        int irq = 0;
    18191
    182         rc = get_my_registers(device, &regs, &irq);
    183         if (rc != EOK) {
    184                 usb_log_error("Failed to get register memory addresses "
    185                     "for %" PRIun ": %s.\n", ddf_dev_get_handle(device),
    186                     str_error(rc));
    187                 goto error;
    188         }
     92        int ret = get_my_registers(device, &reg_base, &reg_size, &irq);
     93        CHECK_RET_RETURN(ret, "Failed to get register memory addresses for %"
     94            PRIun ": %s.\n", ddf_dev_get_handle(device), str_error(ret));
    18995
    19096        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
    191             RNGABSPTR(regs), RNGSZ(regs), irq);
     97            (void *) reg_base, reg_size, irq);
    19298
    193         rc = hc_register_irq_handler(device, &regs, irq, irq_handler);
    194         if (rc != EOK) {
    195                 usb_log_error("Failed to register interrupt handler: %s.\n",
    196                     str_error(rc));
    197                 goto error;
    198         }
     99        const size_t ranges_count = hc_irq_pio_range_count();
     100        const size_t cmds_count = hc_irq_cmd_count();
     101        irq_pio_range_t irq_ranges[ranges_count];
     102        irq_cmd_t irq_cmds[cmds_count];
     103        irq_code_t irq_code = {
     104                .rangecount = ranges_count,
     105                .ranges = irq_ranges,
     106                .cmdcount = cmds_count,
     107                .cmds = irq_cmds
     108        };
    199109
    200         ih_registered = true;
     110        ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
     111            sizeof(irq_cmds), reg_base, reg_size);
     112        CHECK_RET_RETURN(ret, "Failed to gen IRQ code: %s.\n", str_error(ret));
     113
     114        /* Register handler to avoid interrupt lockup */
     115        ret = register_interrupt_handler(device, irq, irq_handler, &irq_code);
     116        CHECK_RET_RETURN(ret,
     117            "Failed to register irq handler: %s.\n", str_error(ret));
    201118
    202119        /* Try to enable interrupts */
    203120        bool interrupts = false;
    204         rc = enable_interrupts(device);
    205         if (rc != EOK) {
     121        ret = enable_interrupts(device);
     122        if (ret != EOK) {
    206123                usb_log_warning("Failed to enable interrupts: %s."
    207                     " Falling back to polling\n", str_error(rc));
     124                    " Falling back to polling\n", str_error(ret));
    208125                /* We don't need that handler */
    209126                unregister_interrupt_handler(device, irq);
    210                 ih_registered = false;
    211127        } else {
    212128                usb_log_debug("Hw interrupts enabled.\n");
     
    214130        }
    215131
    216         rc = hc_init(&instance->hc, &regs, interrupts);
    217         if (rc != EOK) {
    218                 usb_log_error("Failed to init ohci_hcd: %s.\n", str_error(rc));
    219                 goto error;
     132        /* Initialize generic HCD driver */
     133        ret = hcd_ddf_setup_hc(device, USB_SPEED_FULL,
     134            BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
     135        if (ret != EOK) {
     136                unregister_interrupt_handler(device, irq);
     137                return ret;
    220138        }
    221139
    222         hc_inited = true;
     140// TODO: Undo hcd_setup_device
     141#define CHECK_RET_CLEAN_RETURN(ret, message...) \
     142if (ret != EOK) { \
     143        unregister_interrupt_handler(device, irq); \
     144        CHECK_RET_RETURN(ret, message); \
     145} else (void)0
    223146
    224         rc = ddf_fun_bind(instance->hc_fun);
    225         if (rc != EOK) {
    226                 usb_log_error("Failed to bind OHCI device function: %s.\n",
    227                     str_error(rc));
    228                 goto error;
    229         }
     147        hc_t *hc_impl = malloc(sizeof(hc_t));
     148        ret = hc_impl ? EOK : ENOMEM;
     149        CHECK_RET_CLEAN_RETURN(ret, "Failed to allocate driver structure.\n");
    230150
    231         rc = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY);
    232         if (rc != EOK) {
    233                 usb_log_error("Failed to add OHCI to HC category: %s.\n",
    234                     str_error(rc));
    235                 goto error;
    236         }
     151        /* Initialize OHCI HC */
     152        ret = hc_init(hc_impl, reg_base, reg_size, interrupts);
     153        CHECK_RET_CLEAN_RETURN(ret, "Failed to init hc: %s.\n", str_error(ret));
    237154
    238         rc = hc_register_hub(&instance->hc, instance->rh_fun);
    239         if (rc != EOK) {
    240                 usb_log_error("Failed to register OHCI root hub: %s.\n",
    241                     str_error(rc));
    242                 goto error;
    243         }
     155        /* Connect OHCI to generic HCD */
     156        hcd_set_implementation(dev_to_hcd(device), hc_impl,
     157            hc_schedule, ohci_endpoint_init, ohci_endpoint_fini);
    244158
    245         return EOK;
     159        /* HC should be running OK. We can add root hub */
     160        ret = hcd_ddf_setup_root_hub(device);
     161        CHECK_RET_CLEAN_RETURN(ret,
     162            "Failed to register OHCI root hub: %s.\n", str_error(ret));
    246163
    247 error:
    248         if (hc_inited)
    249                 hc_fini(&instance->hc);
    250         if (ih_registered)
    251                 unregister_interrupt_handler(device, irq);
    252         if (instance->hc_fun != NULL)
    253                 ddf_fun_destroy(instance->hc_fun);
    254         if (instance->rh_fun != NULL)
    255                 ddf_fun_destroy(instance->rh_fun);
    256         return rc;
     164        return ret;
    257165}
    258166/**
Note: See TracChangeset for help on using the changeset viewer.