Ignore:
File:
1 edited

Legend:

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

    r7de1988c r772a172  
    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>
    4641
     42#include <usb/host/ddf_helpers.h>
     43
    4744#include "ohci.h"
    48 #include "res.h"
    4945#include "hc.h"
    5046
    51 typedef struct ohci {
    52         ddf_fun_t *hc_fun;
    53         ddf_fun_t *rh_fun;
    5447
    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 }
    6248/** IRQ handling callback, identifies device
    6349 *
     
    6955{
    7056        assert(dev);
    71 
    72         ohci_t *ohci = dev_to_ohci(dev);
    73         if (!ohci) {
     57        hcd_t *hcd = dev_to_hcd(dev);
     58        if (!hcd || !hcd->driver.data) {
    7459                usb_log_warning("Interrupt on device that is not ready.\n");
    7560                return;
    7661        }
     62
    7763        const uint16_t status = IPC_GET_ARG1(*call);
    78         hc_interrupt(&ohci->hc, status);
     64        hc_interrupt(hcd->driver.data, status);
    7965}
    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 };
    13166
    13267/** Initialize hc and rh ddf structures and their respective drivers.
     
    14378int device_setup_ohci(ddf_dev_t *device)
    14479{
    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) {
     80        hw_res_list_parsed_t hw_res;
     81        int ret = hcd_ddf_get_registers(device, &hw_res);
     82        if (ret != EOK ||
     83            hw_res.irqs.count != 1 || hw_res.mem_ranges.count != 1) {
    18484                usb_log_error("Failed to get register memory addresses "
    18585                    "for %" PRIun ": %s.\n", ddf_dev_get_handle(device),
    186                     str_error(rc));
    187                 goto error;
     86                    str_error(ret));
     87                return ret;
    18888        }
     89        addr_range_t regs = hw_res.mem_ranges.ranges[0];
     90        const int irq = hw_res.irqs.irqs[0];
     91        hw_res_list_parsed_clean(&hw_res);
    18992
    19093        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
    19194            RNGABSPTR(regs), RNGSZ(regs), irq);
    19295
    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;
     96        /* Initialize generic HCD driver */
     97        ret = hcd_ddf_setup_hc(device, USB_SPEED_FULL,
     98            BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
     99        if (ret != EOK) {
     100                usb_log_error("Failed to setup generic hcd structures: %s.",
     101                    str_error(ret));
     102                return ret;
    198103        }
    199104
    200         ih_registered = true;
     105        hc_t *hc = malloc(sizeof(hc_t));
     106        if (!hc) {
     107                usb_log_error("Failed to allocate driver structure.\n");
     108                ret = ENOMEM;
     109                goto ddf_hc_clean;
     110        }
    201111
    202112        /* Try to enable interrupts */
    203113        bool interrupts = false;
    204         rc = enable_interrupts(device);
    205         if (rc != EOK) {
     114        ret = hcd_ddf_setup_interrupts(device, &regs, irq, irq_handler,
     115            hc_gen_irq_code);
     116        if (ret != EOK) {
    206117                usb_log_warning("Failed to enable interrupts: %s."
    207                     " Falling back to polling\n", str_error(rc));
     118                    " Falling back to polling\n", str_error(ret));
    208119                /* We don't need that handler */
    209120                unregister_interrupt_handler(device, irq);
    210                 ih_registered = false;
    211121        } else {
    212122                usb_log_debug("Hw interrupts enabled.\n");
     
    214124        }
    215125
    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;
     126        /* Initialize OHCI HC */
     127        ret = hc_init(hc, &regs, interrupts);
     128        if (ret != EOK) {
     129                usb_log_error("Failed to init hc: %s.\n", str_error(ret));
     130                goto unregister_irq;
    220131        }
    221132
    222         hc_inited = true;
     133        /* Connect OHCI to generic HCD */
     134        hcd_set_implementation(dev_to_hcd(device), hc,
     135            hc_schedule, ohci_endpoint_init, ohci_endpoint_fini);
    223136
    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;
     137        /* HC should be running OK. We can add root hub */
     138        ret = hcd_ddf_setup_root_hub(device);
     139        if (ret != EOK) {
     140                usb_log_error("Failed to register OHCI root hub: %s.\n",
     141                    str_error(ret));
     142                hc_fini(hc);
     143unregister_irq:
     144                unregister_interrupt_handler(device, irq);
     145                free(hc);
     146ddf_hc_clean:
     147                hcd_ddf_clean_hc(device);
    229148        }
    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;
     149        return ret;
    257150}
    258151/**
Note: See TracChangeset for help on using the changeset viewer.