Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/uhci-hcd/main.c

    r9351353 ra7e2f0d  
    3333 */
    3434#include <ddf/driver.h>
     35#include <ddf/interrupt.h>
     36#include <device/hw_res.h>
    3537#include <errno.h>
    3638#include <str_error.h>
    3739
     40#include <usb_iface.h>
    3841#include <usb/ddfiface.h>
    3942#include <usb/debug.h>
    4043
    4144#include "iface.h"
     45#include "pci.h"
     46#include "root_hub.h"
    4247#include "uhci.h"
    4348
     
    5560};
    5661/*----------------------------------------------------------------------------*/
    57 /** Initializes a new ddf driver instance for uhci hc and hub.
     62/** IRQ handling callback, identifies devic
     63 *
     64 * @param[in] dev DDF instance of the device to use.
     65 * @param[in] iid (Unused).
     66 * @param[in] call Pointer to the call that represents interrupt.
     67 */
     68static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
     69{
     70        assert(dev);
     71        uhci_t *hc = dev_to_uhci(dev);
     72        uint16_t status = IPC_GET_ARG1(*call);
     73        assert(hc);
     74        uhci_interrupt(hc, status);
     75}
     76/*----------------------------------------------------------------------------*/
     77/** Initializes a new ddf driver instance of UHCI hcd.
    5878 *
    5979 * @param[in] device DDF instance of the device to initialize.
     
    6585int uhci_add_device(ddf_dev_t *device)
    6686{
     87        assert(device);
     88        uhci_t *hcd = NULL;
     89#define CHECK_RET_FREE_HC_RETURN(ret, message...) \
     90if (ret != EOK) { \
     91        usb_log_error(message); \
     92        if (hcd != NULL) \
     93                free(hcd); \
     94        return ret; \
     95}
     96
    6797        usb_log_info("uhci_add_device() called\n");
    68         assert(device);
    69         uhci_t *uhci = malloc(sizeof(uhci_t));
    70         if (uhci == NULL) {
    71                 usb_log_error("Failed to allocate UHCI driver.\n");
    72                 return ENOMEM;
     98
     99        uintptr_t io_reg_base = 0;
     100        size_t io_reg_size = 0;
     101        int irq = 0;
     102
     103        int ret =
     104            pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
     105        CHECK_RET_FREE_HC_RETURN(ret,
     106            "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
     107        usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
     108            io_reg_base, io_reg_size, irq);
     109
     110        ret = pci_disable_legacy(device);
     111        CHECK_RET_FREE_HC_RETURN(ret,
     112            "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
     113
     114#if 0
     115        ret = pci_enable_interrupts(device);
     116        if (ret != EOK) {
     117                usb_log_warning(
     118                    "Failed(%d) to enable interrupts, fall back to polling.\n",
     119                    ret);
    73120        }
     121#endif
    74122
    75         int ret = uhci_init(uhci, device);
    76         if (ret != EOK) {
    77                 usb_log_error("Failed to initialzie UHCI driver.\n");
    78                 return ret;
    79         }
    80         device->driver_data = uhci;
     123        hcd = malloc(sizeof(uhci_t));
     124        ret = (hcd != NULL) ? EOK : ENOMEM;
     125        CHECK_RET_FREE_HC_RETURN(ret,
     126            "Failed(%d) to allocate memory for uhci hcd.\n", ret);
     127
     128        ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size);
     129        CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret);
     130#undef CHECK_RET_FREE_HC_RETURN
     131
     132        /*
     133         * We might free hcd, but that does not matter since no one
     134         * else would access driver_data anyway.
     135         */
     136        device->driver_data = hcd;
     137
     138        ddf_fun_t *rh = NULL;
     139#define CHECK_RET_FINI_FREE_RETURN(ret, message...) \
     140if (ret != EOK) { \
     141        usb_log_error(message); \
     142        if (hcd != NULL) {\
     143                uhci_fini(hcd); \
     144                free(hcd); \
     145        } \
     146        if (rh != NULL) \
     147                free(rh); \
     148        return ret; \
     149}
     150
     151        /* It does no harm if we register this on polling */
     152        ret = register_interrupt_handler(device, irq, irq_handler,
     153            &hcd->interrupt_code);
     154        CHECK_RET_FINI_FREE_RETURN(ret,
     155            "Failed(%d) to register interrupt handler.\n", ret);
     156
     157        ret = setup_root_hub(&rh, device);
     158        CHECK_RET_FINI_FREE_RETURN(ret,
     159            "Failed(%d) to setup UHCI root hub.\n", ret);
     160        rh->driver_data = hcd->ddf_instance;
     161
     162        ret = ddf_fun_bind(rh);
     163        CHECK_RET_FINI_FREE_RETURN(ret,
     164            "Failed(%d) to register UHCI root hub.\n", ret);
     165
    81166        return EOK;
     167#undef CHECK_RET_FINI_FREE_RETURN
    82168}
    83169/*----------------------------------------------------------------------------*/
Note: See TracChangeset for help on using the changeset viewer.