Ignore:
File:
1 edited

Legend:

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

    r952bc66 r7de1988c  
    3434 */
    3535
    36 #include <assert.h>
     36/* XXX Fix this */
     37#define _DDF_DATA_IMPLANT
     38
    3739#include <errno.h>
     40#include <str_error.h>
    3841#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>
    43 
     42#include <usb_iface.h>
    4443#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 
    5047#include "ohci.h"
    51 #include "ohci_endpoint.h"
     48#include "res.h"
    5249#include "hc.h"
    5350
    54 
     51typedef struct ohci {
     52        ddf_fun_t *hc_fun;
     53        ddf_fun_t *rh_fun;
     54
     55        hc_t hc;
     56} ohci_t;
     57
     58static inline ohci_t *dev_to_ohci(ddf_dev_t *dev)
     59{
     60        return ddf_dev_data_get(dev);
     61}
    5562/** IRQ handling callback, identifies device
    5663 *
     
    6269{
    6370        assert(dev);
    64         hcd_t *hcd = dev_to_hcd(dev);
    65         if (!hcd || !hcd->driver.data) {
     71
     72        ohci_t *ohci = dev_to_ohci(dev);
     73        if (!ohci) {
    6674                usb_log_warning("Interrupt on device that is not ready.\n");
    6775                return;
    6876        }
    69 
    7077        const uint16_t status = IPC_GET_ARG1(*call);
    71         hc_interrupt(hcd->driver.data, status);
    72 }
     78        hc_interrupt(&ohci->hc, status);
     79}
     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 */
     87static 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 */
     104static 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 */
     117static 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) */
     123static ddf_dev_ops_t hc_ops = {
     124        .interfaces[USBHC_DEV_IFACE] = &hcd_iface,
     125};
     126
     127/** Standard USB RH options (RH interface) */
     128static ddf_dev_ops_t rh_ops = {
     129        .interfaces[USB_DEV_IFACE] = &usb_iface,
     130};
    73131
    74132/** Initialize hc and rh ddf structures and their respective drivers.
     
    85143int device_setup_ohci(ddf_dev_t *device)
    86144{
    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) {
     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) {
    91184                usb_log_error("Failed to get register memory addresses "
    92185                    "for %" PRIun ": %s.\n", ddf_dev_get_handle(device),
    93                     str_error(ret));
    94                 return ret;
    95         }
    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);
     186                    str_error(rc));
     187                goto error;
     188        }
    99189
    100190        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
    101191            RNGABSPTR(regs), RNGSZ(regs), irq);
    102192
    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;
    110         }
    111 
    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         }
     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        }
     199
     200        ih_registered = true;
    118201
    119202        /* Try to enable interrupts */
    120203        bool interrupts = false;
    121         ret = hcd_ddf_setup_interrupts(device, &regs, irq, irq_handler,
    122             hc_gen_irq_code);
    123         if (ret != EOK) {
     204        rc = enable_interrupts(device);
     205        if (rc != EOK) {
    124206                usb_log_warning("Failed to enable interrupts: %s."
    125                     " Falling back to polling\n", str_error(ret));
     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;
    126211        } else {
    127212                usb_log_debug("Hw interrupts enabled.\n");
     
    129214        }
    130215
    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;
    136         }
    137 
    138         /* Connect OHCI to generic HCD */
    139         hcd_set_implementation(dev_to_hcd(device), hc,
    140             hc_schedule, ohci_endpoint_init, ohci_endpoint_fini);
    141 
    142         /* HC should be running OK. We can add root hub */
    143         ret = hcd_ddf_setup_root_hub(device);
    144         if (ret != EOK) {
     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;
     220        }
     221
     222        hc_inited = true;
     223
     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        }
     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) {
    145240                usb_log_error("Failed to register OHCI root hub: %s.\n",
    146                     str_error(ret));
    147                 hc_fini(hc);
    148 unregister_irq:
     241                    str_error(rc));
     242                goto error;
     243        }
     244
     245        return EOK;
     246
     247error:
     248        if (hc_inited)
     249                hc_fini(&instance->hc);
     250        if (ih_registered)
    149251                unregister_interrupt_handler(device, irq);
    150                 free(hc);
    151 ddf_hc_clean:
    152                 hcd_ddf_clean_hc(device);
    153         }
    154         return ret;
     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;
    155257}
    156258/**
Note: See TracChangeset for help on using the changeset viewer.