Ignore:
File:
1 edited

Legend:

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

    r7de1988c r952bc66  
    3434 */
    3535
    36 /* XXX Fix this */
    37 #define _DDF_DATA_IMPLANT
     36#include <assert.h>
     37#include <errno.h>
     38#include <ddf/interrupt.h>
     39#include <device/hw_res_parsed.h>
     40#include <stdbool.h>
     41#include <str_error.h>
     42#include <sys/types.h>
    3843
    39 #include <errno.h>
    40 #include <str_error.h>
    41 #include <ddf/interrupt.h>
    42 #include <usb_iface.h>
    4344#include <usb/usb.h>
    44 #include <usb/ddfiface.h>
    4545#include <usb/debug.h>
    4646
     47#include <usb/host/ddf_helpers.h>
     48#include <usb/host/usb_bus.h>
     49
    4750#include "ohci.h"
    48 #include "res.h"
     51#include "ohci_endpoint.h"
    4952#include "hc.h"
    5053
    51 typedef struct ohci {
    52         ddf_fun_t *hc_fun;
    53         ddf_fun_t *rh_fun;
    5454
    55         hc_t hc;
    56 } ohci_t;
    57 
    58 static inline ohci_t *dev_to_ohci(ddf_dev_t *dev)
    59 {
    60         return ddf_dev_data_get(dev);
    61 }
    6255/** IRQ handling callback, identifies device
    6356 *
     
    6962{
    7063        assert(dev);
    71 
    72         ohci_t *ohci = dev_to_ohci(dev);
    73         if (!ohci) {
     64        hcd_t *hcd = dev_to_hcd(dev);
     65        if (!hcd || !hcd->driver.data) {
    7466                usb_log_warning("Interrupt on device that is not ready.\n");
    7567                return;
    7668        }
     69
    7770        const uint16_t status = IPC_GET_ARG1(*call);
    78         hc_interrupt(&ohci->hc, status);
     71        hc_interrupt(hcd->driver.data, status);
    7972}
    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 };
    13173
    13274/** Initialize hc and rh ddf structures and their respective drivers.
     
    14385int device_setup_ohci(ddf_dev_t *device)
    14486{
    145         bool ih_registered = false;
    146         bool hc_inited = false;
    147         int rc;
    148 
    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;
    180         int irq = 0;
    181 
    182         rc = get_my_registers(device, &regs, &irq);
    183         if (rc != EOK) {
     87        hw_res_list_parsed_t hw_res;
     88        int ret = hcd_ddf_get_registers(device, &hw_res);
     89        if (ret != EOK ||
     90            hw_res.irqs.count != 1 || hw_res.mem_ranges.count != 1) {
    18491                usb_log_error("Failed to get register memory addresses "
    18592                    "for %" PRIun ": %s.\n", ddf_dev_get_handle(device),
    186                     str_error(rc));
    187                 goto error;
     93                    str_error(ret));
     94                return ret;
    18895        }
     96        addr_range_t regs = hw_res.mem_ranges.ranges[0];
     97        const int irq = hw_res.irqs.irqs[0];
     98        hw_res_list_parsed_clean(&hw_res);
    18999
    190100        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
    191101            RNGABSPTR(regs), RNGSZ(regs), irq);
    192102
    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;
     103        /* Initialize generic HCD driver */
     104        ret = hcd_ddf_setup_hc(device, USB_SPEED_FULL,
     105            BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
     106        if (ret != EOK) {
     107                usb_log_error("Failed to setup generic hcd structures: %s.",
     108                    str_error(ret));
     109                return ret;
    198110        }
    199111
    200         ih_registered = true;
     112        hc_t *hc = malloc(sizeof(hc_t));
     113        if (!hc) {
     114                usb_log_error("Failed to allocate driver structure.\n");
     115                ret = ENOMEM;
     116                goto ddf_hc_clean;
     117        }
    201118
    202119        /* Try to enable interrupts */
    203120        bool interrupts = false;
    204         rc = enable_interrupts(device);
    205         if (rc != EOK) {
     121        ret = hcd_ddf_setup_interrupts(device, &regs, irq, irq_handler,
     122            hc_gen_irq_code);
     123        if (ret != EOK) {
    206124                usb_log_warning("Failed to enable interrupts: %s."
    207                     " Falling back to polling\n", str_error(rc));
    208                 /* We don't need that handler */
    209                 unregister_interrupt_handler(device, irq);
    210                 ih_registered = false;
     125                    " Falling back to polling\n", str_error(ret));
    211126        } else {
    212127                usb_log_debug("Hw interrupts enabled.\n");
     
    214129        }
    215130
    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;
     131        /* Initialize OHCI HC */
     132        ret = hc_init(hc, &regs, interrupts);
     133        if (ret != EOK) {
     134                usb_log_error("Failed to init hc: %s.\n", str_error(ret));
     135                goto unregister_irq;
    220136        }
    221137
    222         hc_inited = true;
     138        /* Connect OHCI to generic HCD */
     139        hcd_set_implementation(dev_to_hcd(device), hc,
     140            hc_schedule, ohci_endpoint_init, ohci_endpoint_fini);
    223141
    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;
     142        /* HC should be running OK. We can add root hub */
     143        ret = hcd_ddf_setup_root_hub(device);
     144        if (ret != EOK) {
     145                usb_log_error("Failed to register OHCI root hub: %s.\n",
     146                    str_error(ret));
     147                hc_fini(hc);
     148unregister_irq:
     149                unregister_interrupt_handler(device, irq);
     150                free(hc);
     151ddf_hc_clean:
     152                hcd_ddf_clean_hc(device);
    229153        }
    230 
    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         }
    237 
    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         }
    244 
    245         return EOK;
    246 
    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;
     154        return ret;
    257155}
    258156/**
Note: See TracChangeset for help on using the changeset viewer.