Changeset a720ff6 in mainline for uspace/drv/bus/usb/uhci/uhci.c


Ignore:
Timestamp:
2012-12-20T15:42:35Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
53332b5b
Parents:
d09791e6
Message:

uhci: Use helper routines provided by libusbhost

File:
1 edited

Legend:

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

    rd09791e6 ra720ff6  
    4343#include <usb/ddfiface.h>
    4444#include <usb/debug.h>
     45#include <usb/host/hcd.h>
    4546
    4647#include "uhci.h"
     
    5051#include "root_hub.h"
    5152
    52 /** Structure representing both functions of UHCI hc, USB host controller
    53  * and USB root hub */
    54 typedef struct uhci {
    55         /** Pointer to DDF representation of UHCI host controller */
    56         ddf_fun_t *hc_fun;
    57         /** Pointer to DDF representation of UHCI root hub */
    58         ddf_fun_t *rh_fun;
    59 
    60         /** Internal driver's representation of UHCI host controller */
    61         hc_t hc;
    62         /** Internal driver's representation of UHCI root hub */
    63         rh_t rh;
    64 } uhci_t;
    65 
    66 static inline uhci_t *dev_to_uhci(ddf_dev_t *dev)
    67 {
    68         return ddf_dev_data_get(dev);
    69 }
    7053
    7154/** IRQ handling callback, forward status from call to diver structure.
     
    7861{
    7962        assert(dev);
    80         uhci_t *uhci = dev_to_uhci(dev);
    81         if (!uhci) {
     63        hcd_t *hcd = dev_to_hcd(dev);
     64        if (!hcd || !hcd->private_data) {
    8265                usb_log_error("Interrupt on not yet initialized device.\n");
    8366                return;
    8467        }
    8568        const uint16_t status = IPC_GET_ARG1(*call);
    86         hc_interrupt(&uhci->hc, status);
     69        hc_interrupt(hcd->private_data, status);
    8770}
    88 
    89 /** Operations supported by the HC driver */
    90 static ddf_dev_ops_t hc_ops = {
    91         .interfaces[USBHC_DEV_IFACE] = &hcd_iface, /* see iface.h/c */
    92 };
    93 
    94 /** Gets handle of the respective hc.
    95  *
    96  * @param[in] fun DDF function of uhci device.
    97  * @param[out] handle Host cotnroller handle.
    98  * @return Error code.
    99  */
    100 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
    101 {
    102         ddf_fun_t *hc_fun = dev_to_uhci(ddf_fun_get_dev(fun))->hc_fun;
    103         assert(hc_fun);
    104 
    105         if (handle != NULL)
    106                 *handle = ddf_fun_get_handle(hc_fun);
    107         return EOK;
    108 }
    109 
    110 /** USB interface implementation used by RH */
    111 static usb_iface_t usb_iface = {
    112         .get_hc_handle = usb_iface_get_hc_handle,
    113 };
    114 
    115 /** Get root hub hw resources (I/O registers).
    116  *
    117  * @param[in] fun Root hub function.
    118  * @return Pointer to the resource list used by the root hub.
    119  */
    120 static hw_resource_list_t *get_resource_list(ddf_fun_t *fun)
    121 {
    122         rh_t *rh = ddf_fun_data_get(fun);
    123         assert(rh);
    124         return &rh->resource_list;
    125 }
    126 
    127 /** Interface to provide the root hub driver with hw info */
    128 static hw_res_ops_t hw_res_iface = {
    129         .get_resource_list = get_resource_list,
    130         .enable_interrupt = NULL,
    131 };
    132 
    133 /** RH function support for uhci_rhd */
    134 static ddf_dev_ops_t rh_ops = {
    135         .interfaces[USB_DEV_IFACE] = &usb_iface,
    136         .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface
    137 };
    13871
    13972/** Initialize hc and rh DDF structures and their respective drivers.
     
    15285                return EBADMEM;
    15386
    154         uhci_t *instance = ddf_dev_data_alloc(device, sizeof(uhci_t));
    155         if (instance == NULL) {
    156                 usb_log_error("Failed to allocate OHCI driver.\n");
    157                 return ENOMEM;
    158         }
    159 
    160 #define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
     87#define CHECK_RET_RETURN(ret, message...) \
    16188if (ret != EOK) { \
    162         if (instance->hc_fun) \
    163                 ddf_fun_destroy(instance->hc_fun); \
    164         if (instance->rh_fun) {\
    165                 ddf_fun_destroy(instance->rh_fun); \
    166         } \
    16789        usb_log_error(message); \
    16890        return ret; \
    16991} else (void)0
    170 
    171         instance->rh_fun = NULL;
    172         instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci_hc");
    173         int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
    174         CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n");
    175         ddf_fun_set_ops(instance->hc_fun, &hc_ops);
    176         ddf_fun_data_implant(instance->hc_fun, &instance->hc.generic);
    177 
    178         instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh");
    179         ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
    180         CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n");
    181         ddf_fun_set_ops(instance->rh_fun, &rh_ops);
    182         ddf_fun_data_implant(instance->rh_fun, &instance->rh);
    18392
    18493        uintptr_t reg_base = 0;
     
    18695        int irq = 0;
    18796
    188         ret = get_my_registers(device, &reg_base, &reg_size, &irq);
    189         CHECK_RET_DEST_FREE_RETURN(ret,
    190             "Failed to get I/O addresses for %" PRIun ": %s.\n",
     97        int ret = get_my_registers(device, &reg_base, &reg_size, &irq);
     98        CHECK_RET_RETURN(ret, "Failed to get I/O region for %" PRIun ": %s.\n",
    19199            ddf_dev_get_handle(device), str_error(ret));
    192100        usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n",
    193101            (void *) reg_base, reg_size, irq);
    194 
    195         ret = disable_legacy(device);
    196         CHECK_RET_DEST_FREE_RETURN(ret,
    197             "Failed to disable legacy USB: %s.\n", str_error(ret));
    198102
    199103        const size_t ranges_count = hc_irq_pio_range_count();
     
    203107        ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
    204108            sizeof(irq_cmds), reg_base, reg_size);
    205         CHECK_RET_DEST_FREE_RETURN(ret,
    206             "Failed to generate IRQ commands: %s.\n", str_error(ret));
     109        CHECK_RET_RETURN(ret, "Failed to generate IRQ commands: %s.\n",
     110            str_error(ret));
    207111
    208112        irq_code_t irq_code = {
     
    215119        /* Register handler to avoid interrupt lockup */
    216120        ret = register_interrupt_handler(device, irq, irq_handler, &irq_code);
    217         CHECK_RET_DEST_FREE_RETURN(ret,
    218             "Failed to register interrupt handler: %s.\n", str_error(ret));
     121        CHECK_RET_RETURN(ret, "Failed to register interrupt handler: %s.\n",
     122            str_error(ret));
     123       
     124        ret = disable_legacy(device);
     125        CHECK_RET_RETURN(ret, "Failed to disable legacy USB: %s.\n",
     126            str_error(ret));
    219127
    220128        bool interrupts = false;
     
    228136        }
    229137
    230         ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
    231         CHECK_RET_DEST_FREE_RETURN(ret,
     138        ddf_fun_t *hc_fun = NULL;
     139        ret = hcd_setup_device(device, &hc_fun);
     140        CHECK_RET_RETURN(ret, "Failed to setup UHCI HCD.\n");
     141       
     142        hc_t *hc = malloc(sizeof(hc_t));
     143        ret = hc ? EOK : ENOMEM;
     144        CHECK_RET_RETURN(ret, "Failed to allocate UHCI HC structure.\n");
     145
     146        ret = hc_init(hc, (void*)reg_base, reg_size, interrupts);
     147        CHECK_RET_RETURN(ret,
    232148            "Failed to init uhci_hcd: %s.\n", str_error(ret));
    233149
     150        hcd_set_implementation(dev_to_hcd(device), hc, hc_schedule, NULL, NULL);
     151
     152// TODO: Undo hcd_setup_device
    234153#define CHECK_RET_FINI_RETURN(ret, message...) \
    235154if (ret != EOK) { \
    236         hc_fini(&instance->hc); \
    237         CHECK_RET_DEST_FREE_RETURN(ret, message); \
     155        hc_fini(hc); \
     156        CHECK_RET_RETURN(ret, message); \
    238157        return ret; \
    239158} else (void)0
    240159
    241         ret = ddf_fun_bind(instance->hc_fun);
    242         CHECK_RET_FINI_RETURN(ret, "Failed to bind UHCI device function: %s.\n",
    243             str_error(ret));
    244 
    245         ret = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY);
    246         CHECK_RET_FINI_RETURN(ret,
    247             "Failed to add UHCI to HC class: %s.\n", str_error(ret));
    248 
    249         ret = rh_init(&instance->rh, instance->rh_fun,
    250             (uintptr_t)instance->hc.registers + 0x10, 4);
     160        ret = rh_init(device, (uintptr_t)hc->registers + 0x10, 4,
     161            ddf_fun_get_handle(hc_fun));
    251162        CHECK_RET_FINI_RETURN(ret,
    252163            "Failed to setup UHCI root hub: %s.\n", str_error(ret));
    253 
    254         ret = ddf_fun_bind(instance->rh_fun);
    255         CHECK_RET_FINI_RETURN(ret,
    256             "Failed to register UHCI root hub: %s.\n", str_error(ret));
    257164
    258165        return EOK;
Note: See TracChangeset for help on using the changeset viewer.