Changeset a720ff6 in mainline


Ignore:
Timestamp:
2012-12-20T15:42:35Z (11 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

Location:
uspace/drv/bus/usb/uhci
Files:
5 edited

Legend:

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

    rd09791e6 ra720ff6  
    8585static int hc_init_mem_structures(hc_t *instance);
    8686static int hc_init_transfer_lists(hc_t *instance);
    87 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    8887
    8988static int hc_interrupt_emulator(void *arg);
     
    235234
    236235#undef CHECK_RET_RETURN
    237 
    238         hcd_init(&instance->generic, USB_SPEED_FULL,
    239             BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
    240 
    241         instance->generic.private_data = instance;
    242         instance->generic.schedule = hc_schedule;
    243         instance->generic.ep_add_hook = NULL;
    244236
    245237        hc_init_hw(instance);
  • uspace/drv/bus/usb/uhci/hc.h

    rd09791e6 ra720ff6  
    9090/** Main UHCI driver structure */
    9191typedef struct hc {
    92         /** Generic HCD driver structure */
    93         hcd_t generic;
    94 
    9592        /** Addresses of I/O registers */
    9693        uhci_regs_t *registers;
     
    125122void hc_interrupt(hc_t *instance, uint16_t status);
    126123int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
     124int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    127125
    128126/** Safely dispose host controller internal structures
  • uspace/drv/bus/usb/uhci/root_hub.c

    rd09791e6 ra720ff6  
    3636#include <str_error.h>
    3737#include <stdio.h>
     38#include <ops/hw_res.h>
    3839
     40#include <usb_iface.h>
    3941#include <usb/debug.h>
    4042
    4143#include "root_hub.h"
     44/** DDF support structure for uhci_rhd driver, provides I/O resources */
     45typedef struct {
     46        /** List of resources available to the root hub. */
     47        hw_resource_list_t resource_list;
     48        /** The only resource in the RH resource list */
     49        hw_resource_t io_regs;
    4250
     51        devman_handle_t hc_handle;
     52} rh_t;
     53
     54/** Gets handle of the respective hc.
     55 *
     56 * @param[in] fun DDF function of uhci device.
     57 * @param[out] handle Host cotnroller handle.
     58 * @return Error code.
     59 */
     60static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
     61{
     62        assert(fun);
     63        rh_t *rh = ddf_fun_data_get(fun);
     64
     65        if (handle != NULL)
     66                *handle = rh->hc_handle;
     67        return EOK;
     68}
     69
     70/** USB interface implementation used by RH */
     71static usb_iface_t usb_iface = {
     72        .get_hc_handle = usb_iface_get_hc_handle,
     73};
     74
     75/** Get root hub hw resources (I/O registers).
     76 *
     77 * @param[in] fun Root hub function.
     78 * @return Pointer to the resource list used by the root hub.
     79 */
     80static hw_resource_list_t *get_resource_list(ddf_fun_t *fun)
     81{
     82        assert(fun);
     83        rh_t *rh = ddf_fun_data_get(fun);
     84        assert(rh);
     85        return &rh->resource_list;
     86}
     87
     88/** Interface to provide the root hub driver with hw info */
     89static hw_res_ops_t hw_res_iface = {
     90        .get_resource_list = get_resource_list,
     91        .enable_interrupt = NULL,
     92};
     93
     94/** RH function support for uhci_rhd */
     95static ddf_dev_ops_t rh_ops = {
     96        .interfaces[USB_DEV_IFACE] = &usb_iface,
     97        .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface
     98};
    4399/** Root hub initialization
    44100 * @param[in] instance RH structure to initialize
     
    48104 * @return Error code.
    49105 */
    50 int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
     106int rh_init(ddf_dev_t *device, uintptr_t reg_addr, size_t reg_size,
     107    devman_handle_t handle)
    51108{
    52         assert(instance);
    53         assert(fun);
     109        assert(device);
     110       
     111        ddf_fun_t *fun = ddf_fun_create(device, fun_inner, "uhci_rh");
     112        if (!fun) {
     113                usb_log_error("Failed to create UHCI RH function.\n");
     114                return ENOMEM;
     115        }
     116        ddf_fun_set_ops(fun, &rh_ops);
     117
     118        rh_t *instance = ddf_fun_data_alloc(fun, sizeof(rh_t));
    54119
    55120        /* Initialize resource structure */
     
    62127        instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN;
    63128
    64         const int ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);
     129        instance->hc_handle = handle;   
     130
     131        int ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);
    65132        if (ret != EOK) {
    66133                usb_log_error("Failed to add root hub match id: %s\n",
    67134                    str_error(ret));
     135                ddf_fun_destroy(fun);
    68136        }
     137
     138        ret = ddf_fun_bind(fun);
     139        if (ret != EOK) {
     140                usb_log_error("Failed to bind root function: %s\n",
     141                    str_error(ret));
     142                ddf_fun_destroy(fun);
     143        }
     144
     145        usb_log_fatal("RH ready, hc handle: %"PRIun"\n", handle);
    69146        return ret;
    70147}
  • uspace/drv/bus/usb/uhci/root_hub.h

    rd09791e6 ra720ff6  
    3737
    3838#include <ddf/driver.h>
    39 #include <ops/hw_res.h>
    4039
    41 /** DDF support structure for uhci_rhd driver, provides I/O resources */
    42 typedef struct rh {
    43         /** List of resources available to the root hub. */
    44         hw_resource_list_t resource_list;
    45         /** The only resource in the RH resource list */
    46         hw_resource_t io_regs;
    47 } rh_t;
    48 
    49 int rh_init(
    50     rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size);
     40int rh_init(ddf_dev_t *device, uintptr_t reg_addr, size_t reg_size,
     41    devman_handle_t handle);
    5142
    5243#endif
  • 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.