Changeset 32fb6bce in mainline


Ignore:
Timestamp:
2017-12-18T22:50:21Z (6 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7f70d1c
Parents:
1ea0bbf
git-author:
Ondřej Hlavatý <aearsis@…> (2017-12-18 22:04:50)
git-committer:
Ondřej Hlavatý <aearsis@…> (2017-12-18 22:50:21)
Message:

usbhost: refactoring

This commit moves interrupt, status and schedule to bus
operations. Then the purpose of hcd_t is better defined, and split into
hc_driver_t and hc_device_t. hc_driver_t is used to wrap driver
implementation by the library (similar to how usb_driver_t is used to
wrap usb device drivers). hc_device_t is used as a parent for hc_t
inside drivers, and is allocated inside the DDF device node.

To support these changes, some local identifiers were renamed, some
functions were moved and/or renamed and their arguments changed. The
most notable one being hcd_send_batch → bus_device_send_batch.

Location:
uspace
Files:
33 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ehci/ehci_bus.c

    r1ea0bbf r32fb6bce  
    162162        .parent = &usb2_bus_ops,
    163163
     164        .interrupt = ehci_hc_interrupt,
     165        .status = ehci_hc_status,
    164166        .endpoint_destroy = ehci_endpoint_destroy,
    165167        .endpoint_create = ehci_endpoint_create,
     
    171173        .batch_create = ehci_create_batch,
    172174        .batch_destroy = ehci_destroy_batch,
     175        .batch_schedule = ehci_hc_schedule,
    173176};
    174177
    175 int ehci_bus_init(ehci_bus_t *bus, hcd_t *hcd, hc_t *hc)
     178int ehci_bus_init(ehci_bus_t *bus, hc_t *hc)
    176179{
    177180        assert(hc);
     
    181184        bus_t *bus_base = (bus_t *) bus;
    182185
    183         usb2_bus_init(usb2_bus, hcd, BANDWIDTH_AVAILABLE_USB11);
     186        usb2_bus_init(usb2_bus, BANDWIDTH_AVAILABLE_USB11);
    184187        bus_base->ops = &ehci_bus_ops;
    185188
  • uspace/drv/bus/usb/ehci/ehci_bus.h

    r1ea0bbf r32fb6bce  
    6363void ehci_bus_prepare_ops(void);
    6464
    65 int ehci_bus_init(ehci_bus_t *, hcd_t *, hc_t *);
     65int ehci_bus_init(ehci_bus_t *, hc_t *);
    6666
    6767/** Get and convert assigned ehci_endpoint_t structure
    6868 * @param[in] ep USBD endpoint structure.
    69  * @return Pointer to assigned hcd endpoint structure
     69 * @return Pointer to assigned ehci endpoint structure
    7070 */
    7171static inline ehci_endpoint_t * ehci_endpoint_get(const endpoint_t *ep)
  • uspace/drv/bus/usb/ehci/hc.c

    r1ea0bbf r32fb6bce  
    9797 * @return Error code.
    9898 */
    99 int ehci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
     99int hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
    100100{
    101101        assert(code);
    102102        assert(hw_res);
    103 
    104         hc_t *instance = hcd_get_driver_data(hcd);
     103        hc_t *instance = hcd_to_hc(hcd);
    105104
    106105        if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1)
     
    149148 * @return Error code
    150149 */
    151 int hc_init(hc_t *instance, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
    152 {
    153         assert(instance);
     150int hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
     151{
     152        hc_t *instance = hcd_to_hc(hcd);
    154153        assert(hw_res);
    155154        if (hw_res->mem_ranges.count != 1 ||
     
    190189            &instance->rh, instance->caps, instance->registers, "ehci rh");
    191190
    192         ehci_bus_init(&instance->bus, hcd, instance);
     191        ehci_bus_init(&instance->bus, instance);
     192        hc_device_setup(hcd, (bus_t *) &instance->bus);
    193193        return EOK;
    194194}
     
    198198 * @param[in] instance Host controller structure to use.
    199199 */
    200 void hc_fini(hc_t *instance)
     200int hc_gone(hc_device_t *instance)
    201201{
    202202        assert(instance);
     203        return EOK;
    203204        //TODO: stop the hw
    204205#if 0
     
    263264}
    264265
    265 int ehci_hc_status(hcd_t *hcd, uint32_t *status)
    266 {
    267         assert(hcd);
    268         hc_t *instance = hcd_get_driver_data(hcd);
    269         assert(instance);
     266int ehci_hc_status(bus_t *bus_base, uint32_t *status)
     267{
     268        assert(bus_base);
    270269        assert(status);
     270
     271        ehci_bus_t *bus = (ehci_bus_t *) bus_base;
     272        hc_t *hc = bus->hc;
     273        assert(hc);
     274
    271275        *status = 0;
    272         if (instance->registers) {
    273                 *status = EHCI_RD(instance->registers->usbsts);
    274                 EHCI_WR(instance->registers->usbsts, *status);
    275         }
    276         usb_log_debug2("HC(%p): Read status: %x", instance, *status);
     276        if (hc->registers) {
     277                *status = EHCI_RD(hc->registers->usbsts);
     278                EHCI_WR(hc->registers->usbsts, *status);
     279        }
     280        usb_log_debug2("HC(%p): Read status: %x", hc, *status);
    277281        return EOK;
    278282}
     
    284288 * @return Error code.
    285289 */
    286 int ehci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    287 {
    288         assert(hcd);
    289         hc_t *instance = hcd_get_driver_data(hcd);
    290         assert(instance);
     290int ehci_hc_schedule(usb_transfer_batch_t *batch)
     291{
     292        assert(batch);
     293
     294        ehci_bus_t *bus = (ehci_bus_t *) endpoint_get_bus(batch->ep);
     295        hc_t *hc = bus->hc;
     296        assert(hc);
    291297
    292298        /* Check for root hub communication */
    293         if (batch->target.address == ehci_rh_get_address(&instance->rh)) {
     299        if (batch->target.address == ehci_rh_get_address(&hc->rh)) {
    294300                usb_log_debug("HC(%p): Scheduling BATCH(%p) for RH(%p)",
    295                     instance, batch, &instance->rh);
    296                 return ehci_rh_schedule(&instance->rh, batch);
     301                    hc, batch, &hc->rh);
     302                return ehci_rh_schedule(&hc->rh, batch);
    297303        }
    298304
     
    303309                return err;
    304310
    305         fibril_mutex_lock(&instance->guard);
    306         usb_log_debug2("HC(%p): Appending BATCH(%p)", instance, batch);
    307         list_append(&ehci_batch->link, &instance->pending_batches);
    308         usb_log_debug("HC(%p): Committing BATCH(%p)", instance, batch);
     311        fibril_mutex_lock(&hc->guard);
     312        usb_log_debug2("HC(%p): Appending BATCH(%p)", hc, batch);
     313        list_append(&ehci_batch->link, &hc->pending_batches);
     314        usb_log_debug("HC(%p): Committing BATCH(%p)", hc, batch);
    309315        ehci_transfer_batch_commit(ehci_batch);
    310316
    311         fibril_mutex_unlock(&instance->guard);
     317        fibril_mutex_unlock(&hc->guard);
    312318        return EOK;
    313319}
     
    318324 * @param[in] status Value of the status register at the time of interrupt.
    319325 */
    320 void ehci_hc_interrupt(hcd_t *hcd, uint32_t status)
    321 {
    322         assert(hcd);
    323         hc_t *instance = hcd_get_driver_data(hcd);
    324         status = EHCI_RD(status);
    325         assert(instance);
    326 
    327         usb_log_debug2("HC(%p): Interrupt: %"PRIx32, instance, status);
     326void ehci_hc_interrupt(bus_t *bus_base, uint32_t status)
     327{
     328        assert(bus_base);
     329
     330        ehci_bus_t *bus = (ehci_bus_t *) bus_base;
     331        hc_t *hc = bus->hc;
     332        assert(hc);
     333
     334        usb_log_debug2("HC(%p): Interrupt: %"PRIx32, hc, status);
    328335        if (status & USB_STS_PORT_CHANGE_FLAG) {
    329                 ehci_rh_interrupt(&instance->rh);
     336                ehci_rh_interrupt(&hc->rh);
    330337        }
    331338
    332339        if (status & USB_STS_IRQ_ASYNC_ADVANCE_FLAG) {
    333                 fibril_mutex_lock(&instance->guard);
    334                 usb_log_debug2("HC(%p): Signaling doorbell", instance);
    335                 fibril_condvar_broadcast(&instance->async_doorbell);
    336                 fibril_mutex_unlock(&instance->guard);
     340                fibril_mutex_lock(&hc->guard);
     341                usb_log_debug2("HC(%p): Signaling doorbell", hc);
     342                fibril_condvar_broadcast(&hc->async_doorbell);
     343                fibril_mutex_unlock(&hc->guard);
    337344        }
    338345
    339346        if (status & (USB_STS_IRQ_FLAG | USB_STS_ERR_IRQ_FLAG)) {
    340                 fibril_mutex_lock(&instance->guard);
    341 
    342                 usb_log_debug2("HC(%p): Scanning %lu pending batches", instance,
    343                         list_count(&instance->pending_batches));
    344                 list_foreach_safe(instance->pending_batches, current, next) {
     347                fibril_mutex_lock(&hc->guard);
     348
     349                usb_log_debug2("HC(%p): Scanning %lu pending batches", hc,
     350                        list_count(&hc->pending_batches));
     351                list_foreach_safe(hc->pending_batches, current, next) {
    345352                        ehci_transfer_batch_t *batch =
    346353                            ehci_transfer_batch_from_link(current);
     
    351358                        }
    352359                }
    353                 fibril_mutex_unlock(&instance->guard);
     360                fibril_mutex_unlock(&hc->guard);
    354361        }
    355362
    356363        if (status & USB_STS_HOST_ERROR_FLAG) {
    357                 usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", instance);
     364                usb_log_fatal("HCD(%p): HOST SYSTEM ERROR!", hc);
    358365                //TODO do something here
    359366        }
     
    364371 * @param[in] instance EHCI hc driver structure.
    365372 */
    366 int hc_start(hc_t *instance, bool interrupts)
    367 {
    368         assert(instance);
     373int hc_start(hc_device_t *hcd)
     374{
     375        hc_t *instance = hcd_to_hc(hcd);
    369376        usb_log_debug("HC(%p): Starting HW.", instance);
    370377
  • uspace/drv/bus/usb/ehci/hc.h

    r1ea0bbf r32fb6bce  
    5555/** Main EHCI driver structure */
    5656typedef struct hc {
     57        /* Common device header */
     58        hc_device_t base;
     59
    5760        /** Memory mapped CAPS register area */
    5861        ehci_caps_regs_t *caps;
     
    8588} hc_t;
    8689
    87 int hc_init(hc_t *instance, hcd_t *hcd, const hw_res_list_parsed_t *hw_res);
    88 int hc_start(hc_t *instance, bool interrupts);
    89 void hc_fini(hc_t *instance);
     90static inline hc_t *hcd_to_hc(hc_device_t *hcd)
     91{
     92        assert(hcd);
     93        return (hc_t *) hcd;
     94}
    9095
    91 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep);
    92 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep);
     96void hc_enqueue_endpoint(hc_t *, const endpoint_t *);
     97void hc_dequeue_endpoint(hc_t *, const endpoint_t *);
    9398
    94 int ehci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res);
     99/* Boottime operations */
     100int hc_add(hc_device_t *, const hw_res_list_parsed_t *);
     101int hc_start(hc_device_t *);
     102int hc_gen_irq_code(irq_code_t *, hc_device_t *, const hw_res_list_parsed_t *);
     103int hc_gone(hc_device_t *);
    95104
    96 void ehci_hc_interrupt(hcd_t *hcd, uint32_t status);
    97 int ehci_hc_status(hcd_t *hcd, uint32_t *status);
    98 int ehci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
     105/** Runtime operations */
     106void ehci_hc_interrupt(bus_t *, uint32_t);
     107int ehci_hc_status(bus_t *, uint32_t *);
     108int ehci_hc_schedule(usb_transfer_batch_t *);
     109
    99110#endif
    100111/**
  • uspace/drv/bus/usb/ehci/main.c

    r1ea0bbf r32fb6bce  
    3535 */
    3636
    37 #include <ddf/driver.h>
    38 #include <ddf/interrupt.h>
    39 #include <device/hw_res.h>
    40 #include <errno.h>
    41 #include <str_error.h>
    4237#include <io/logctl.h>
    43 
    44 #include <usb_iface.h>
    45 #include <usb/debug.h>
     38#include <usb/host/hcd.h>
    4639#include <usb/host/ddf_helpers.h>
    4740
     
    5144#define NAME "ehci"
    5245
    53 static int ehci_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *);
    54 static int ehci_driver_claim(hcd_t *, ddf_dev_t *);
    55 static int ehci_driver_start(hcd_t *, bool);
    56 static void ehci_driver_fini(hcd_t *);
     46static const hc_driver_t ehci_driver = {
     47        .name = NAME,
     48        .hc_device_size = sizeof(hc_t),
    5749
    58 static const ddf_hc_driver_t ehci_hc_driver = {
    59         .name = "EHCI-PCI",
    60         .init = ehci_driver_init,
    61         .irq_code_gen = ehci_hc_gen_irq_code,
    62         .claim = ehci_driver_claim,
    63         .start = ehci_driver_start,
     50        .hc_add = hc_add,
     51        .irq_code_gen = hc_gen_irq_code,
     52        .claim = disable_legacy,
     53        .start = hc_start,
    6454        .setup_root_hub = hcd_setup_virtual_root_hub,
    65         .fini = ehci_driver_fini,
    66         .ops = {
    67                 .schedule       = ehci_hc_schedule,
    68                 .irq_hook       = ehci_hc_interrupt,
    69                 .status_hook    = ehci_hc_status,
    70         }
     55        .hc_gone = hc_gone,
    7156};
    72 
    73 
    74 static int ehci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, ddf_dev_t *device)
    75 {
    76         assert(hcd);
    77         assert(hcd_get_driver_data(hcd) == NULL);
    78 
    79         hc_t *instance = malloc(sizeof(hc_t));
    80         if (!instance)
    81                 return ENOMEM;
    82 
    83         const int ret = hc_init(instance, hcd, res);
    84         if (ret == EOK) {
    85                 hcd_set_implementation(hcd, instance, &ehci_hc_driver.ops, &instance->bus.base.base);
    86         } else {
    87                 free(instance);
    88         }
    89         return ret;
    90 }
    91 
    92 static int ehci_driver_claim(hcd_t *hcd, ddf_dev_t *dev)
    93 {
    94         hc_t *instance = hcd_get_driver_data(hcd);
    95         assert(instance);
    96 
    97         return disable_legacy(instance, dev);
    98 }
    99 
    100 static int ehci_driver_start(hcd_t *hcd, bool irq) {
    101         hc_t *instance = hcd_get_driver_data(hcd);
    102         assert(instance);
    103 
    104         return hc_start(instance, irq);
    105 }
    106 
    107 static void ehci_driver_fini(hcd_t *hcd)
    108 {
    109         assert(hcd);
    110         hc_t *hc = hcd_get_driver_data(hcd);
    111         if (hc)
    112                 hc_fini(hc);
    113 
    114         free(hc);
    115         hcd_set_implementation(hcd, NULL, NULL, NULL);
    116 }
    117 
    118 /** Initializes a new ddf driver instance of EHCI hcd.
    119  *
    120  * @param[in] device DDF instance of the device to initialize.
    121  * @return Error code.
    122  */
    123 static int ehci_dev_add(ddf_dev_t *device)
    124 {
    125         usb_log_debug("ehci_dev_add() called\n");
    126         assert(device);
    127 
    128         return hcd_ddf_add_hc(device, &ehci_hc_driver);
    129 
    130 }
    131 
    132 static int ehci_fun_online(ddf_fun_t *fun)
    133 {
    134         return hcd_ddf_device_online(fun);
    135 }
    136 
    137 static int ehci_fun_offline(ddf_fun_t *fun)
    138 {
    139         return hcd_ddf_device_offline(fun);
    140 }
    141 
    142 
    143 static const driver_ops_t ehci_driver_ops = {
    144         .dev_add = ehci_dev_add,
    145         .fun_online = ehci_fun_online,
    146         .fun_offline = ehci_fun_offline
    147 };
    148 
    149 static const driver_t ehci_driver = {
    150         .name = NAME,
    151         .driver_ops = &ehci_driver_ops
    152 };
    153 
    15457
    15558/** Initializes global driver structures (NONE).
     
    16568        log_init(NAME);
    16669        logctl_set_log_level(NAME, LVL_NOTE);
    167         return ddf_driver_main(&ehci_driver);
     70        return hc_driver_main(&ehci_driver);
    16871}
    16972
  • uspace/drv/bus/usb/ehci/res.c

    r1ea0bbf r32fb6bce  
    4545#include <pci_dev_iface.h>
    4646
     47#include "hc.h"
    4748#include "res.h"
    4849#include "ehci_regs.h"
     
    172173}
    173174
    174 int disable_legacy(hc_t *hc, ddf_dev_t *device)
     175int disable_legacy(hc_device_t *hcd)
    175176{
    176         assert(device);
    177 
    178         async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
     177        hc_t *hc = hcd_to_hc(hcd);
     178
     179        async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev);
    179180        if (parent_sess == NULL)
    180181                return ENOMEM;
  • uspace/drv/bus/usb/ehci/res.h

    r1ea0bbf r32fb6bce  
    3636#define DRV_EHCI_PCI_H
    3737
    38 #include <ddf/driver.h>
    39 #include <device/hw_res_parsed.h>
     38typedef struct hc_device hc_device_t;
    4039
    41 #include "hc.h"
    42 
    43 extern int disable_legacy(hc_t *, ddf_dev_t *);
     40extern int disable_legacy(hc_device_t *);
    4441
    4542#endif
  • uspace/drv/bus/usb/ohci/hc.c

    r1ea0bbf r32fb6bce  
    101101 * @return Error code.
    102102 */
    103 int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
     103int hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
    104104{
    105105        assert(code);
     
    149149 * @return Error code
    150150 */
    151 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res)
    152 {
    153         assert(instance);
     151int hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
     152{
     153        hc_t *instance = hcd_to_hc(hcd);
    154154        assert(hw_res);
    155155        if (hw_res->mem_ranges.count != 1 ||
     
    186186 * @param[in] instance Host controller structure to use.
    187187 */
    188 void hc_fini(hc_t *instance)
     188int hc_gone(hc_device_t *instance)
    189189{
    190190        assert(instance);
    191191        /* TODO: implement*/
    192 };
     192        return ENOTSUP;
     193}
    193194
    194195void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
     
    260261}
    261262
    262 int ohci_hc_status(hcd_t *hcd, uint32_t *status)
    263 {
    264         assert(hcd);
     263int ohci_hc_status(bus_t *bus_base, uint32_t *status)
     264{
     265        assert(bus_base);
    265266        assert(status);
    266         hc_t *instance = hcd_get_driver_data(hcd);
    267         assert(instance);
    268 
    269         if (instance->registers){
    270                 *status = OHCI_RD(instance->registers->interrupt_status);
    271                 OHCI_WR(instance->registers->interrupt_status, *status);
     267
     268        ohci_bus_t *bus = (ohci_bus_t *) bus_base;
     269        hc_t *hc = bus->hc;
     270        assert(hc);
     271
     272        if (hc->registers){
     273                *status = OHCI_RD(hc->registers->interrupt_status);
     274                OHCI_WR(hc->registers->interrupt_status, *status);
    272275        }
    273276        return EOK;
     
    280283 * @return Error code.
    281284 */
    282 int ohci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    283 {
    284         assert(hcd);
    285         hc_t *instance = hcd_get_driver_data(hcd);
    286         assert(instance);
     285int ohci_hc_schedule(usb_transfer_batch_t *batch)
     286{
     287        assert(batch);
     288
     289        ohci_bus_t *bus = (ohci_bus_t *) endpoint_get_bus(batch->ep);
     290        hc_t *hc = bus->hc;
     291        assert(hc);
    287292
    288293        /* Check for root hub communication */
    289         if (batch->target.address == ohci_rh_get_address(&instance->rh)) {
     294        if (batch->target.address == ohci_rh_get_address(&hc->rh)) {
    290295                usb_log_debug("OHCI root hub request.\n");
    291                 return ohci_rh_schedule(&instance->rh, batch);
     296                return ohci_rh_schedule(&hc->rh, batch);
    292297        }
    293298        ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch);
     
    299304                return err;
    300305
    301         fibril_mutex_lock(&instance->guard);
    302         list_append(&ohci_batch->link, &instance->pending_batches);
     306        fibril_mutex_lock(&hc->guard);
     307        list_append(&ohci_batch->link, &hc->pending_batches);
    303308        ohci_transfer_batch_commit(ohci_batch);
    304309
     
    307312        {
    308313        case USB_TRANSFER_CONTROL:
    309                 OHCI_SET(instance->registers->command_status, CS_CLF);
     314                OHCI_SET(hc->registers->command_status, CS_CLF);
    310315                break;
    311316        case USB_TRANSFER_BULK:
    312                 OHCI_SET(instance->registers->command_status, CS_BLF);
     317                OHCI_SET(hc->registers->command_status, CS_BLF);
    313318                break;
    314319        default:
    315320                break;
    316321        }
    317         fibril_mutex_unlock(&instance->guard);
     322        fibril_mutex_unlock(&hc->guard);
    318323        return EOK;
    319324}
     
    324329 * @param[in] status Value of the status register at the time of interrupt.
    325330 */
    326 void ohci_hc_interrupt(hcd_t *hcd, uint32_t status)
    327 {
    328         assert(hcd);
    329         hc_t *instance = hcd_get_driver_data(hcd);
     331void ohci_hc_interrupt(bus_t *bus_base, uint32_t status)
     332{
     333        assert(bus_base);
     334
     335        ohci_bus_t *bus = (ohci_bus_t *) bus_base;
     336        hc_t *hc = bus->hc;
     337        assert(hc);
     338
    330339        status = OHCI_RD(status);
    331         assert(instance);
     340        assert(hc);
    332341        if ((status & ~I_SF) == 0) /* ignore sof status */
    333342                return;
    334         usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status);
     343        usb_log_debug2("OHCI(%p) interrupt: %x.\n", hc, status);
    335344        if (status & I_RHSC)
    336                 ohci_rh_interrupt(&instance->rh);
     345                ohci_rh_interrupt(&hc->rh);
    337346
    338347        if (status & I_WDH) {
    339                 fibril_mutex_lock(&instance->guard);
    340                 usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
    341                     OHCI_RD(instance->registers->hcca),
    342                     (void *) addr_to_phys(instance->hcca));
     348                fibril_mutex_lock(&hc->guard);
     349                usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", hc->hcca,
     350                    OHCI_RD(hc->registers->hcca),
     351                    (void *) addr_to_phys(hc->hcca));
    343352                usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
    344                     OHCI_RD(instance->registers->periodic_current));
    345 
    346                 link_t *current = list_first(&instance->pending_batches);
    347                 while (current && current != &instance->pending_batches.head) {
     353                    OHCI_RD(hc->registers->periodic_current));
     354
     355                link_t *current = list_first(&hc->pending_batches);
     356                while (current && current != &hc->pending_batches.head) {
    348357                        link_t *next = current->next;
    349358                        ohci_transfer_batch_t *batch =
     
    357366                        current = next;
    358367                }
    359                 fibril_mutex_unlock(&instance->guard);
     368                fibril_mutex_unlock(&hc->guard);
    360369        }
    361370
    362371        if (status & I_UE) {
    363372                usb_log_fatal("Error like no other!\n");
    364                 hc_start(instance);
     373                hc_start(&hc->base);
    365374        }
    366375
     
    374383 * @param[in] instance OHCI hc driver structure.
    375384 */
    376 void hc_gain_control(hc_t *instance)
    377 {
    378         assert(instance);
     385int hc_gain_control(hc_device_t *hcd)
     386{
     387        hc_t *instance = hcd_to_hc(hcd);
    379388
    380389        usb_log_debug("Requesting OHCI control.\n");
     
    409418                C_HCFS_SET(instance->registers->control, C_HCFS_RESET);
    410419                async_usleep(50000);
    411                 return;
     420                return EOK;
    412421        }
    413422
     
    418427                if (hc_status == C_HCFS_OPERATIONAL) {
    419428                        usb_log_info("BIOS driver: HC operational.\n");
    420                         return;
     429                        return EOK;
    421430                }
    422431                /* HC is suspended assert resume for 20ms */
     
    424433                async_usleep(20000);
    425434                usb_log_info("BIOS driver: HC resumed.\n");
    426                 return;
     435                return EOK;
    427436        }
    428437
     
    431440        usb_log_debug("Host controller found in reset state.\n");
    432441        async_usleep(50000);
     442        return EOK;
    433443}
    434444
     
    437447 * @param[in] instance OHCI hc driver structure.
    438448 */
    439 void hc_start(hc_t *instance)
    440 {
     449int hc_start(hc_device_t *hcd)
     450{
     451        hc_t *instance = hcd_to_hc(hcd);
    441452        ohci_rh_init(&instance->rh, instance->registers, "ohci rh");
    442453
     
    489500
    490501        /* Enable interrupts */
    491         if (instance->hw_interrupts) {
     502        if (instance->base.irq_cap >= 0) {
    492503                OHCI_WR(instance->registers->interrupt_enable,
    493504                    OHCI_USED_INTERRUPTS);
     
    508519        usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
    509520            OHCI_RD(instance->registers->control));
     521
     522        return EOK;
    510523}
    511524
     
    555568        memset(&instance->rh, 0, sizeof(instance->rh));
    556569        /* Init queues */
    557         const int ret = hc_init_transfer_lists(instance);
     570        int ret = hc_init_transfer_lists(instance);
    558571        if (ret != EOK) {
    559572                return ret;
     
    574587            instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
    575588
     589        if ((ret = ohci_bus_init(&instance->bus, instance))) {
     590                usb_log_error("HC(%p): Failed to setup bus : %s",
     591                    instance, str_error(ret));
     592                return ret;
     593        }
     594
     595        hc_device_setup(&instance->base, (bus_t *) &instance->bus);
     596
    576597        return EOK;
    577598}
  • uspace/drv/bus/usb/ohci/hc.h

    r1ea0bbf r32fb6bce  
    5858/** Main OHCI driver structure */
    5959typedef struct hc {
     60        /** Common hcd header */
     61        hc_device_t base;
     62
    6063        /** Memory mapped I/O registers area */
    6164        ohci_regs_t *registers;
     
    7073        list_t pending_batches;
    7174
    72         /** Fibril for periodic checks if interrupts can't be used */
    73         fid_t interrupt_emulator;
    74 
    7575        /** Guards schedule and endpoint manipulation */
    7676        fibril_mutex_t guard;
    77 
    78         /** interrupts available */
    79         bool hw_interrupts;
    8077
    8178        /** USB hub emulation structure */
     
    8683} hc_t;
    8784
    88 extern int hc_init(hc_t *, const hw_res_list_parsed_t *);
    89 extern void hc_gain_control(hc_t *instance);
    90 extern void hc_start(hc_t *instance);
    91 extern void hc_fini(hc_t *);
     85static inline hc_t * hcd_to_hc(hc_device_t *hcd)
     86{
     87        assert(hcd);
     88        return (hc_t *) hcd;
     89}
     90
     91extern int hc_add(hc_device_t *, const hw_res_list_parsed_t *);
     92extern int hc_gen_irq_code(irq_code_t *, hc_device_t *, const hw_res_list_parsed_t *);
     93extern int hc_gain_control(hc_device_t *);
     94extern int hc_start(hc_device_t *);
     95extern int hc_gone(hc_device_t *);
    9296
    9397extern void hc_enqueue_endpoint(hc_t *, const endpoint_t *);
    9498extern void hc_dequeue_endpoint(hc_t *, const endpoint_t *);
    9599
    96 int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res);
    97 
    98 extern void ohci_hc_interrupt(hcd_t *, uint32_t);
    99 extern int ohci_hc_status(hcd_t *, uint32_t *);
    100 extern int ohci_hc_schedule(hcd_t *, usb_transfer_batch_t *);
     100extern int ohci_hc_schedule(usb_transfer_batch_t *);
     101extern int ohci_hc_status(bus_t *, uint32_t *);
     102extern void ohci_hc_interrupt(bus_t *, uint32_t);
    101103
    102104#endif
  • uspace/drv/bus/usb/ohci/main.c

    r1ea0bbf r32fb6bce  
    4848
    4949#define NAME "ohci"
    50 static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *);
    51 static int ohci_driver_start(hcd_t *, bool);
    52 static int ohci_driver_claim(hcd_t *, ddf_dev_t *);
    53 static void ohci_driver_fini(hcd_t *);
    5450
    55 static const ddf_hc_driver_t ohci_hc_driver = {
    56         .irq_code_gen = ohci_hc_gen_irq_code,
    57         .init = ohci_driver_init,
    58         .claim = ohci_driver_claim,
    59         .start = ohci_driver_start,
     51static const hc_driver_t ohci_driver = {
     52        .name = NAME,
     53        .hc_device_size = sizeof(hc_t),
     54
     55        .hc_add = hc_add,
     56        .irq_code_gen = hc_gen_irq_code,
     57        .claim = hc_gain_control,
     58        .start = hc_start,
    6059        .setup_root_hub = hcd_setup_virtual_root_hub,
    61         .fini = ohci_driver_fini,
    62         .name = "OHCI",
    63         .ops = {
    64                 .schedule       = ohci_hc_schedule,
    65                 .irq_hook       = ohci_hc_interrupt,
    66                 .status_hook    = ohci_hc_status,
    67         },
    68 };
    69 
    70 
    71 static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, ddf_dev_t *device)
    72 {
    73         int err;
    74 
    75         assert(hcd);
    76         assert(hcd_get_driver_data(hcd) == NULL);
    77 
    78         hc_t *instance = malloc(sizeof(hc_t));
    79         if (!instance)
    80                 return ENOMEM;
    81 
    82         if ((err = hc_init(instance, res)) != EOK)
    83                 goto err;
    84 
    85         if ((err = ohci_bus_init(&instance->bus, hcd, instance)))
    86                 goto err;
    87 
    88         hcd_set_implementation(hcd, instance, &ohci_hc_driver.ops, &instance->bus.base.base);
    89 
    90         return EOK;
    91 
    92 err:
    93         free(instance);
    94         return err;
    95 }
    96 
    97 static int ohci_driver_claim(hcd_t *hcd, ddf_dev_t *dev)
    98 {
    99         hc_t *hc = hcd_get_driver_data(hcd);
    100         assert(hc);
    101 
    102         hc_gain_control(hc);
    103 
    104         return EOK;
    105 }
    106 
    107 static int ohci_driver_start(hcd_t *hcd, bool interrupts)
    108 {
    109         hc_t *hc = hcd_get_driver_data(hcd);
    110         assert(hc);
    111 
    112         hc->hw_interrupts = interrupts;
    113         hc_start(hc);
    114         return EOK;
    115 }
    116 
    117 static void ohci_driver_fini(hcd_t *hcd)
    118 {
    119         assert(hcd);
    120         hc_t *hc = hcd_get_driver_data(hcd);
    121         if (hc)
    122                 hc_fini(hc);
    123 
    124         hcd_set_implementation(hcd, NULL, NULL, NULL);
    125         free(hc);
    126 }
    127 
    128 /** Initializes a new ddf driver instance of OHCI hcd.
    129  *
    130  * @param[in] device DDF instance of the device to initialize.
    131  * @return Error code.
    132  */
    133 static int ohci_dev_add(ddf_dev_t *device)
    134 {
    135         usb_log_debug("ohci_dev_add() called\n");
    136         assert(device);
    137         return hcd_ddf_add_hc(device, &ohci_hc_driver);
    138 }
    139 
    140 static int ohci_fun_online(ddf_fun_t *fun)
    141 {
    142         return hcd_ddf_device_online(fun);
    143 }
    144 
    145 static int ohci_fun_offline(ddf_fun_t *fun)
    146 {
    147         return hcd_ddf_device_offline(fun);
    148 }
    149 
    150 
    151 static const driver_ops_t ohci_driver_ops = {
    152         .dev_add = ohci_dev_add,
    153         .fun_online = ohci_fun_online,
    154         .fun_offline = ohci_fun_offline
    155 };
    156 
    157 static const driver_t ohci_driver = {
    158         .name = NAME,
    159         .driver_ops = &ohci_driver_ops
     60        .hc_gone = hc_gone,
    16061};
    16162
     
    17172{
    17273        log_init(NAME);
    173         return ddf_driver_main(&ohci_driver);
     74        return hc_driver_main(&ohci_driver);
    17475}
    17576
  • uspace/drv/bus/usb/ohci/ohci_bus.c

    r1ea0bbf r32fb6bce  
    158158        .parent = &usb2_bus_ops,
    159159
     160        .interrupt = ohci_hc_interrupt,
     161        .status = ohci_hc_status,
     162
    160163        .endpoint_destroy = ohci_endpoint_destroy,
    161164        .endpoint_create = ohci_endpoint_create,
     
    167170        .batch_create = ohci_create_batch,
    168171        .batch_destroy = ohci_destroy_batch,
     172        .batch_schedule = ohci_hc_schedule,
    169173};
    170174
    171175
    172 int ohci_bus_init(ohci_bus_t *bus, hcd_t *hcd, hc_t *hc)
     176int ohci_bus_init(ohci_bus_t *bus, hc_t *hc)
    173177{
    174178        assert(hc);
    175179        assert(bus);
    176180
    177 
    178181        usb2_bus_t *usb2_bus = (usb2_bus_t *) bus;
    179182        bus_t *bus_base = (bus_t *) bus;
    180183
    181         usb2_bus_init(usb2_bus, hcd, BANDWIDTH_AVAILABLE_USB11);
     184        usb2_bus_init(usb2_bus, BANDWIDTH_AVAILABLE_USB11);
    182185        bus_base->ops = &ohci_bus_ops;
    183186
  • uspace/drv/bus/usb/ohci/ohci_bus.h

    r1ea0bbf r32fb6bce  
    6262} ohci_bus_t;
    6363
    64 int ohci_bus_init(ohci_bus_t *, hcd_t *, hc_t *);
     64int ohci_bus_init(ohci_bus_t *, hc_t *);
    6565
    6666/** Get and convert assigned ohci_endpoint_t structure
  • uspace/drv/bus/usb/uhci/hc.c

    r1ea0bbf r32fb6bce  
    9595
    9696static void hc_init_hw(const hc_t *instance);
    97 static int hc_init_mem_structures(hc_t *instance, hcd_t *);
     97static int hc_init_mem_structures(hc_t *instance, hc_device_t *);
    9898static int hc_init_transfer_lists(hc_t *instance);
    9999
     
    107107 * @return Error code.
    108108 */
    109 int uhci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
     109int hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
    110110{
    111111        assert(code);
     
    156156 * - resume from suspend state (not implemented)
    157157 */
    158 void uhci_hc_interrupt(hcd_t *hcd, uint32_t status)
    159 {
    160         assert(hcd);
    161         hc_t *instance = hcd_get_driver_data(hcd);
    162         assert(instance);
     158static void hc_interrupt(bus_t *bus, uint32_t status)
     159{
     160        hc_t *instance = bus_to_hc(bus);
     161
    163162        /* Lower 2 bits are transaction error and transaction complete */
    164163        if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
     
    199198                } else {
    200199                        usb_log_fatal("Too many UHCI hardware failures!.\n");
    201                         hc_fini(instance);
     200                        hc_gone(&instance->base);
    202201                }
    203202        }
     
    215214 * interrupt fibrils.
    216215 */
    217 int hc_init(hc_t *instance, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
    218 {
    219         assert(instance);
     216int hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
     217{
     218        hc_t *instance = hcd_to_hc(hcd);
    220219        assert(hw_res);
    221220        if (hw_res->io_ranges.count != 1 ||
     
    249248}
    250249
    251 void hc_start(hc_t *instance)
    252 {
     250int hc_start(hc_device_t *hcd)
     251{
     252        hc_t *instance = hcd_to_hc(hcd);
    253253        hc_init_hw(instance);
    254254        (void)hc_debug_checker;
    255255
    256         uhci_rh_init(&instance->rh, instance->registers->ports, "uhci");
     256        return uhci_rh_init(&instance->rh, instance->registers->ports, "uhci");
    257257}
    258258
     
    261261 * @param[in] instance Host controller structure to use.
    262262 */
    263 void hc_fini(hc_t *instance)
     263int hc_gone(hc_device_t *instance)
    264264{
    265265        assert(instance);
    266266        //TODO Implement
     267        return ENOTSUP;
    267268}
    268269
     
    294295        pio_write_32(&registers->flbaseadd, pa);
    295296
    296         if (instance->hw_interrupts) {
     297        if (instance->base.irq_cap >= 0) {
    297298                /* Enable all interrupts, but resume interrupt */
    298299                pio_write_16(&instance->registers->usbintr,
     
    320321}
    321322
     323static int hc_status(bus_t *, uint32_t *);
     324static int hc_schedule(usb_transfer_batch_t *);
     325
    322326static const bus_ops_t uhci_bus_ops = {
    323327        .parent = &usb2_bus_ops,
    324328
     329        .interrupt = hc_interrupt,
     330        .status = hc_status,
     331
    325332        .endpoint_count_bw = bandwidth_count_usb11,
    326333        .batch_create = create_transfer_batch,
     334        .batch_schedule = hc_schedule,
    327335        .batch_destroy = destroy_transfer_batch,
    328336};
     
    338346 *  - frame list page (needs to be one UHCI hw accessible 4K page)
    339347 */
    340 int hc_init_mem_structures(hc_t *instance, hcd_t *hcd)
     348int hc_init_mem_structures(hc_t *instance, hc_device_t *hcd)
    341349{
    342350        int err;
    343351        assert(instance);
    344352
    345         if ((err = usb2_bus_init(&instance->bus, hcd, BANDWIDTH_AVAILABLE_USB11)))
     353        if ((err = usb2_bus_init(&instance->bus, BANDWIDTH_AVAILABLE_USB11)))
    346354                return err;
    347355
    348356        bus_t *bus = (bus_t *) &instance->bus;
    349357        bus->ops = &uhci_bus_ops;
     358
     359        hc_device_setup(&instance->base, bus);
    350360
    351361        /* Init USB frame list page */
     
    438448}
    439449
    440 int uhci_hc_status(hcd_t *hcd, uint32_t *status)
    441 {
    442         assert(hcd);
     450static int hc_status(bus_t *bus, uint32_t *status)
     451{
     452        hc_t *instance = bus_to_hc(bus);
    443453        assert(status);
    444         hc_t *instance = hcd_get_driver_data(hcd);
    445         assert(instance);
    446454
    447455        *status = 0;
     
    462470 * Checks for bandwidth availability and appends the batch to the proper queue.
    463471 */
    464 int uhci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    465 {
    466         assert(hcd);
    467         hc_t *instance = hcd_get_driver_data(hcd);
    468         assert(instance);
     472static int hc_schedule(usb_transfer_batch_t *batch)
     473{
     474        hc_t *instance = bus_to_hc(endpoint_get_bus(batch->ep));
    469475        assert(batch);
    470476
  • uspace/drv/bus/usb/uhci/hc.h

    r1ea0bbf r32fb6bce  
    100100/** Main UHCI driver structure */
    101101typedef struct hc {
     102        /* Common hc_device header */
     103        hc_device_t base;
     104
    102105        uhci_rh_t rh;
    103106        usb2_bus_t bus;
     
    119122        /** Pointer table to the above lists, helps during scheduling */
    120123        transfer_list_t *transfers[2][4];
    121         /** Indicator of hw interrupts availability */
    122         bool hw_interrupts;
    123124
    124125        /** Number of hw failures detected. */
     
    126127} hc_t;
    127128
    128 extern int hc_init(hc_t *, hcd_t *, const hw_res_list_parsed_t *);
    129 extern void hc_start(hc_t *);
    130 extern void hc_fini(hc_t *);
     129static inline hc_t *hcd_to_hc(hc_device_t *hcd)
     130{
     131        assert(hcd);
     132        return (hc_t *) hcd;
     133}
    131134
    132 extern int uhci_hc_gen_irq_code(irq_code_t *, hcd_t *,const hw_res_list_parsed_t *);
     135static inline hc_t *bus_to_hc(bus_t *bus)
     136{
     137        assert(bus);
     138        return member_to_inst(bus, hc_t, bus);
     139}
    133140
    134 extern void uhci_hc_interrupt(hcd_t *, uint32_t);
    135 extern int uhci_hc_status(hcd_t *, uint32_t *);
    136 extern int uhci_hc_schedule(hcd_t *, usb_transfer_batch_t *);
     141extern int hc_add(hc_device_t *, const hw_res_list_parsed_t *);
     142extern int hc_gen_irq_code(irq_code_t *, hc_device_t *, const hw_res_list_parsed_t *);
     143extern int hc_start(hc_device_t *);
     144extern int hc_gone(hc_device_t *);
    137145
    138146#endif
  • uspace/drv/bus/usb/uhci/main.c

    r1ea0bbf r32fb6bce  
    4949#define NAME "uhci"
    5050
    51 static int uhci_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *);
    52 static int uhci_driver_start(hcd_t *, bool);
    53 static void uhci_driver_fini(hcd_t *);
    54 static int disable_legacy(hcd_t *, ddf_dev_t *);
     51static int disable_legacy(hc_device_t *);
    5552
    56 static const ddf_hc_driver_t uhci_hc_driver = {
    57         .claim = disable_legacy,
    58         .irq_code_gen = uhci_hc_gen_irq_code,
    59         .init = uhci_driver_init,
    60         .start = uhci_driver_start,
     53static const hc_driver_t uhci_driver = {
     54        .name = NAME,
     55        .hc_device_size = sizeof(hc_t),
     56        .claim = disable_legacy,
     57        .irq_code_gen = hc_gen_irq_code,
     58        .hc_add = hc_add,
     59        .start = hc_start,
    6160        .setup_root_hub = hcd_setup_virtual_root_hub,
    62         .fini = uhci_driver_fini,
    63         .name = "UHCI",
    64         .ops = {
    65                 .schedule    = uhci_hc_schedule,
    66                 .irq_hook    = uhci_hc_interrupt,
    67                 .status_hook = uhci_hc_status,
    68         },
     61        .hc_gone = hc_gone,
    6962};
    70 
    71 static int uhci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, ddf_dev_t *device)
    72 {
    73         int err;
    74 
    75         assert(hcd);
    76         assert(hcd_get_driver_data(hcd) == NULL);
    77 
    78         hc_t *instance = malloc(sizeof(hc_t));
    79         if (!instance)
    80                 return ENOMEM;
    81 
    82         if ((err = hc_init(instance, hcd, res)) != EOK)
    83                 goto err;
    84 
    85         hcd_set_implementation(hcd, instance, &uhci_hc_driver.ops, &instance->bus.base);
    86 
    87         return EOK;
    88 
    89 err:
    90         free(instance);
    91         return err;
    92 }
    93 
    94 static int uhci_driver_start(hcd_t *hcd, bool interrupts)
    95 {
    96         assert(hcd);
    97         hc_t *hc = hcd_get_driver_data(hcd);
    98 
    99         hc->hw_interrupts = interrupts;
    100         hc_start(hc);
    101         return EOK;
    102 }
    103 
    104 static void uhci_driver_fini(hcd_t *hcd)
    105 {
    106         assert(hcd);
    107         hc_t *hc = hcd_get_driver_data(hcd);
    108         if (hc)
    109                 hc_fini(hc);
    110 
    111         hcd_set_implementation(hcd, NULL, NULL, NULL);
    112         free(hc);
    113 }
    11463
    11564/** Call the PCI driver with a request to clear legacy support register
     
    11867 * @return Error code.
    11968 */
    120 static int disable_legacy(hcd_t *hcd, ddf_dev_t *device)
     69static int disable_legacy(hc_device_t *hcd)
    12170{
    122         assert(device);
     71        assert(hcd);
    12372
    124         async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
     73        async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev);
    12574        if (parent_sess == NULL)
    12675                return ENOMEM;
     
    13079        return pci_config_space_write_16(parent_sess, 0xc0, 0xaf00);
    13180}
    132 
    133 /** Initialize a new ddf driver instance for uhci hc and hub.
    134  *
    135  * @param[in] device DDF instance of the device to initialize.
    136  * @return Error code.
    137  */
    138 static int uhci_dev_add(ddf_dev_t *device)
    139 {
    140         usb_log_debug2("uhci_dev_add() called\n");
    141         assert(device);
    142         return hcd_ddf_add_hc(device, &uhci_hc_driver);
    143 }
    144 
    145 static int uhci_fun_online(ddf_fun_t *fun)
    146 {
    147         return hcd_ddf_device_online(fun);
    148 }
    149 
    150 static int uhci_fun_offline(ddf_fun_t *fun)
    151 {
    152         return hcd_ddf_device_offline(fun);
    153 }
    154 
    155 static const driver_ops_t uhci_driver_ops = {
    156         .dev_add = uhci_dev_add,
    157         .fun_online = uhci_fun_online,
    158         .fun_offline = uhci_fun_offline
    159 };
    160 
    161 static const driver_t uhci_driver = {
    162         .name = NAME,
    163         .driver_ops = &uhci_driver_ops
    164 };
    165 
    16681
    16782/** Initialize global driver structures (NONE).
     
    17893        log_init(NAME);
    17994        logctl_set_log_level(NAME, LVL_DEBUG2);
    180         return ddf_driver_main(&uhci_driver);
     95        return hc_driver_main(&uhci_driver);
    18196}
    18297/**
  • uspace/drv/bus/usb/vhc/main.c

    r1ea0bbf r32fb6bce  
    6969                return ret;
    7070        }
    71         vhc_init(vhc, dev_to_hcd(dev));
    7271        return EOK;
    7372}
    7473
    75 hcd_ops_t vhc_hc_ops = {
    76         .schedule = vhc_schedule,
    77 };
    78 
    7974static int vhc_dev_add(ddf_dev_t *dev)
    8075{
     76        /* Initialize generic structures */
     77        int ret = hcd_ddf_setup_hc(dev, sizeof(vhc_data_t));
     78        if (ret != EOK) {
     79                usb_log_error("Failed to init HCD structures: %s.\n",
     80                   str_error(ret));
     81                return ret;
     82        }
     83        vhc_data_t *vhc = ddf_dev_data_get(dev);
     84        vhc_init(vhc);
     85
     86        hc_device_setup(&vhc->base, (bus_t *) &vhc->bus);
     87
    8188        /* Initialize virtual structure */
    8289        ddf_fun_t *ctl_fun = NULL;
    83         int ret = vhc_control_node(dev, &ctl_fun);
     90        ret = vhc_control_node(dev, &ctl_fun);
    8491        if (ret != EOK) {
    8592                usb_log_error("Failed to setup control node.\n");
    8693                return ret;
    8794        }
    88         vhc_data_t *data = ddf_fun_data_get(ctl_fun);
    89 
    90         /* Initialize generic structures */
    91         ret = hcd_ddf_setup_hc(dev);
    92         if (ret != EOK) {
    93                 usb_log_error("Failed to init HCD structures: %s.\n",
    94                    str_error(ret));
    95                 ddf_fun_destroy(ctl_fun);
    96                 return ret;
    97         }
    98 
    99         hcd_set_implementation(dev_to_hcd(dev), data, &vhc_hc_ops, &data->bus.base);
    10095
    10196        /* Add virtual hub device */
    102         ret = vhc_virtdev_plug_hub(data, &data->hub, NULL, 0);
     97        ret = vhc_virtdev_plug_hub(vhc, &vhc->hub, NULL, 0);
    10398        if (ret != EOK) {
    10499                usb_log_error("Failed to plug root hub: %s.\n", str_error(ret));
     
    111106         * needs to be ready at this time.
    112107         */
    113         ret = hcd_setup_virtual_root_hub(dev_to_hcd(dev), dev);
     108        ret = hcd_setup_virtual_root_hub(&vhc->base);
    114109        if (ret != EOK) {
    115110                usb_log_error("Failed to init VHC root hub: %s\n",
  • uspace/drv/bus/usb/vhc/transfer.c

    r1ea0bbf r32fb6bce  
    4040static bool is_set_address_transfer(vhc_transfer_t *transfer)
    4141{
    42         if (transfer->batch->target.endpoint != 0) {
    43                 return false;
    44         }
    45         if (transfer->batch->ep->transfer_type != USB_TRANSFER_CONTROL) {
    46                 return false;
    47         }
    48         if (transfer->batch->dir != USB_DIRECTION_OUT) {
     42        if (transfer->batch.target.endpoint != 0) {
     43                return false;
     44        }
     45        if (transfer->batch.ep->transfer_type != USB_TRANSFER_CONTROL) {
     46                return false;
     47        }
     48        if (transfer->batch.dir != USB_DIRECTION_OUT) {
    4949                return false;
    5050        }
    5151        const usb_device_request_setup_packet_t *setup
    52                 = &transfer->batch->setup.packet;
     52                = &transfer->batch.setup.packet;
    5353        if (setup->request_type != 0) {
    5454                return false;
     
    150150        assert(outcome != ENAK);
    151151        assert(transfer);
    152         assert(transfer->batch);
    153         transfer->batch->error = outcome;
    154         transfer->batch->transfered_size = data_transfer_size;
    155         usb_transfer_batch_finish(transfer->batch);
     152        transfer->batch.error = outcome;
     153        transfer->batch.transfered_size = data_transfer_size;
     154        usb_transfer_batch_finish(&transfer->batch);
    156155        free(transfer);
     156}
     157
     158static usb_transfer_batch_t *batch_create(endpoint_t *ep)
     159{
     160        vhc_transfer_t *transfer = calloc(1, sizeof(vhc_transfer_t));
     161        usb_transfer_batch_init(&transfer->batch, ep);
     162        link_initialize(&transfer->link);
     163        return &transfer->batch;
    157164}
    158165
    159166static const bus_ops_t vhc_bus_ops = {
    160167        .parent = &usb2_bus_ops,
     168
    161169        .endpoint_count_bw = bandwidth_count_usb11,
     170        .batch_create = batch_create,
     171        .batch_schedule = vhc_schedule,
    162172};
    163173
    164 int vhc_init(vhc_data_t *instance, hcd_t *hcd)
     174int vhc_init(vhc_data_t *instance)
    165175{
    166176        assert(instance);
    167177        list_initialize(&instance->devices);
    168178        fibril_mutex_initialize(&instance->guard);
    169         usb2_bus_init(&instance->bus, hcd, BANDWIDTH_AVAILABLE_USB11);
     179        usb2_bus_init(&instance->bus, BANDWIDTH_AVAILABLE_USB11);
    170180        instance->bus.base.ops = &vhc_bus_ops;
    171         instance->magic = 0xDEADBEEF;
    172181        return virthub_init(&instance->hub, "root hub");
    173182}
    174183
    175 int vhc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    176 {
    177         assert(hcd);
     184int vhc_schedule(usb_transfer_batch_t *batch)
     185{
    178186        assert(batch);
    179         vhc_data_t *vhc = hcd_get_driver_data(hcd);
     187        vhc_transfer_t *transfer = (vhc_transfer_t *) batch;
     188        vhc_data_t *vhc = bus_to_vhc(endpoint_get_bus(batch->ep));
    180189        assert(vhc);
    181 
    182         vhc_transfer_t *transfer = malloc(sizeof(vhc_transfer_t));
    183         if (!transfer)
    184                 return ENOMEM;
    185         link_initialize(&transfer->link);
    186         transfer->batch = batch;
    187190
    188191        fibril_mutex_lock(&vhc->guard);
     
    192195        list_foreach(vhc->devices, link, vhc_virtdev_t, dev) {
    193196                fibril_mutex_lock(&dev->guard);
    194                 if (dev->address == transfer->batch->target.address) {
     197                if (dev->address == transfer->batch.target.address) {
    195198                        if (!targets) {
    196199                                list_append(&transfer->link, &dev->transfer_queue);
     
    227230                size_t data_transfer_size = 0;
    228231                if (dev->dev_sess) {
    229                         rc = process_transfer_remote(transfer->batch,
     232                        rc = process_transfer_remote(&transfer->batch,
    230233                            dev->dev_sess, &data_transfer_size);
    231234                } else if (dev->dev_local != NULL) {
    232                         rc = process_transfer_local(transfer->batch,
     235                        rc = process_transfer_local(&transfer->batch,
    233236                            dev->dev_local, &data_transfer_size);
    234237                } else {
     
    244247                        if (is_set_address_transfer(transfer)) {
    245248                                usb_device_request_setup_packet_t *setup =
    246                                     (void*) transfer->batch->setup.buffer;
     249                                    (void*) transfer->batch.setup.buffer;
    247250                                dev->address = setup->value;
    248251                                usb_log_debug2("Address changed to %d\n",
  • uspace/drv/bus/usb/vhc/vhcd.h

    r1ea0bbf r32fb6bce  
    3939#include <usbvirt/device.h>
    4040#include <async.h>
     41#include <macros.h>
    4142
    4243#include <usb/host/hcd.h>
    4344#include <usb/host/usb2_bus.h>
     45#include <usb/host/usb_transfer_batch.h>
    4446
    4547#define NAME "vhc"
     
    5658
    5759typedef struct {
    58         uint32_t magic;
     60        hc_device_t base;
     61
     62        usb2_bus_t bus;
     63        ddf_fun_t *virtual_fun;
    5964        list_t devices;
    6065        fibril_mutex_t guard;
    6166        usbvirt_device_t hub;
    62         usb2_bus_t bus;
    6367} vhc_data_t;
    6468
    6569typedef struct {
     70        usb_transfer_batch_t batch;
    6671        link_t link;
    67         usb_transfer_batch_t *batch;
    6872} vhc_transfer_t;
     73
     74static inline vhc_data_t *hcd_to_vhc(hc_device_t *hcd)
     75{
     76        assert(hcd);
     77        return (vhc_data_t *) hcd;
     78}
     79
     80static inline vhc_data_t *bus_to_vhc(bus_t *bus)
     81{
     82        assert(bus);
     83        return member_to_inst(bus, vhc_data_t, bus);
     84}
    6985
    7086void on_client_close(ddf_fun_t *fun);
     
    7793void vhc_virtdev_unplug(vhc_data_t *, uintptr_t);
    7894
    79 int vhc_init(vhc_data_t *instance, hcd_t *);
    80 int vhc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
     95int vhc_init(vhc_data_t *);
     96int vhc_schedule(usb_transfer_batch_t *);
    8197int vhc_transfer_queue_processor(void *arg);
    8298
  • uspace/drv/bus/usb/xhci/bus.c

    r1ea0bbf r32fb6bce  
    111111
    112112        uint16_t max_packet_size;
    113         if ((err = hcd_get_ep0_max_packet_size(&max_packet_size, hc->hcd, &dev->base)))
     113        if ((err = hcd_get_ep0_max_packet_size(&max_packet_size, (bus_t *) &hc->bus, &dev->base)))
    114114                return err;
    115115
     
    168168
    169169        /* Read the device descriptor, derive the match ids */
    170         if ((err = hcd_ddf_device_explore(dev))) {
     170        if ((err = hcd_device_explore(dev))) {
    171171                usb_log_error("Device(%d): Failed to explore device: %s", dev->address, str_error(err));
    172172                goto err_address;
     
    233233        /* Destroy DDF device. */
    234234        /* XXX: Not a good idea, this method should not destroy devices. */
    235         hcd_ddf_device_destroy(dev);
     235        hcd_ddf_fun_destroy(dev);
    236236
    237237        return EOK;
     
    501501        BIND_OP(batch_destroy)
    502502#undef BIND_OP
     503
     504        .interrupt = hc_interrupt,
     505        .status = hc_status,
     506        .batch_schedule = hc_schedule,
    503507};
    504508
     
    507511        assert(bus);
    508512
    509         bus_init(&bus->base, hc->hcd, sizeof(xhci_device_t));
     513        bus_init(&bus->base, sizeof(xhci_device_t));
    510514
    511515        bus->devices_by_slot = calloc(hc->max_slots, sizeof(xhci_device_t *));
  • uspace/drv/bus/usb/xhci/hc.c

    r1ea0bbf r32fb6bce  
    432432 * Used only when polling. Shall supplement the irq_commands.
    433433 */
    434 int hc_status(xhci_hc_t *hc, uint32_t *status)
    435 {
     434int hc_status(bus_t *bus, uint32_t *status)
     435{
     436        xhci_hc_t *hc = bus_to_hc(bus);
    436437        int ip = XHCI_REG_RD(hc->rt_regs->ir, XHCI_INTR_IP);
    437438        if (ip) {
     
    449450}
    450451
    451 int hc_schedule(xhci_hc_t *hc, usb_transfer_batch_t *batch)
     452int hc_schedule(usb_transfer_batch_t *batch)
    452453{
    453454        assert(batch);
    454         assert(batch->ep);
     455        xhci_hc_t *hc = bus_to_hc(endpoint_get_bus(batch->ep));
    455456
    456457        if (!batch->target.address) {
     
    532533}
    533534
    534 void hc_interrupt(xhci_hc_t *hc, uint32_t status)
    535 {
     535void hc_interrupt(bus_t *bus, uint32_t status)
     536{
     537        xhci_hc_t *hc = bus_to_hc(bus);
    536538        status = xhci2host(32, status);
    537539
  • uspace/drv/bus/usb/xhci/hc.h

    r1ea0bbf r32fb6bce  
    5151
    5252typedef struct xhci_hc {
     53        /** Common HC device header */
     54        hc_device_t base;
     55
    5356        /* MMIO range */
    5457        addr_range_t mmio_range;
     
    8689        xhci_port_speed_t speeds [16];
    8790        uint8_t speed_to_psiv [USB_SPEED_MAX];
     91} xhci_hc_t;
    8892
    89         /* TODO: Hack. Figure out a better way. */
    90         hcd_t *hcd;
    91 } xhci_hc_t;
     93static inline xhci_hc_t *bus_to_hc(bus_t *bus)
     94{
     95        assert(bus);
     96        return member_to_inst(bus, xhci_hc_t, bus);
     97}
    9298
    9399typedef struct xhci_endpoint xhci_endpoint_t;
     
    99105int hc_irq_code_gen(irq_code_t *, xhci_hc_t *, const hw_res_list_parsed_t *);
    100106int hc_start(xhci_hc_t *, bool);
    101 int hc_schedule(xhci_hc_t *hc, usb_transfer_batch_t *batch);
    102 int hc_status(xhci_hc_t *, uint32_t *);
    103 void hc_interrupt(xhci_hc_t *, uint32_t);
    104107void hc_fini(xhci_hc_t *);
    105108int hc_ring_doorbell(xhci_hc_t *, unsigned, unsigned);
     
    113116int hc_update_endpoint(xhci_hc_t *, uint32_t, uint8_t, xhci_ep_ctx_t *);
    114117
     118int hc_schedule(usb_transfer_batch_t *batch);
     119int hc_status(bus_t *, uint32_t *);
     120void hc_interrupt(bus_t *, uint32_t);
     121
    115122#endif
    116123
  • uspace/drv/bus/usb/xhci/main.c

    r1ea0bbf r32fb6bce  
    4747#define NAME "xhci"
    4848
    49 static int hc_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *);
    50 static int hcd_irq_code_gen(irq_code_t *, hcd_t *, const hw_res_list_parsed_t *);
    51 static int hcd_claim(hcd_t *, ddf_dev_t *);
    52 static int hcd_start(hcd_t *, bool);
    53 static int hcd_status(hcd_t *, uint32_t *);
    54 static void hcd_interrupt(hcd_t *, uint32_t);
    55 static int hcd_schedule(hcd_t *, usb_transfer_batch_t *);
    56 static void hc_driver_fini(hcd_t *);
     49static inline xhci_hc_t *hcd_to_hc(hc_device_t *hcd)
     50{
     51        assert(hcd);
     52        return (xhci_hc_t *) hcd;
     53}
    5754
    58 static const ddf_hc_driver_t xhci_ddf_hc_driver = {
    59         .name = "XHCI-PCI",
    60         .init = hc_driver_init,
     55static int hcd_hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
     56{
     57        int err;
     58        xhci_hc_t *hc = hcd_to_hc(hcd);
     59        hc_device_setup(hcd, (bus_t *) &hc->bus);
     60
     61        if ((err = hc_init_mmio(hc, hw_res)))
     62                return err;
     63
     64        if ((err = hc_init_memory(hc, hcd->ddf_dev)))
     65                return err;
     66
     67        return EOK;
     68}
     69
     70static int hcd_irq_code_gen(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
     71{
     72        xhci_hc_t *hc = hcd_to_hc(hcd);
     73        return hc_irq_code_gen(code, hc, hw_res);
     74}
     75
     76static int hcd_claim(hc_device_t *hcd)
     77{
     78        xhci_hc_t *hc = hcd_to_hc(hcd);
     79        return hc_claim(hc, hcd->ddf_dev);
     80}
     81
     82static int hcd_start(hc_device_t *hcd)
     83{
     84        xhci_hc_t *hc = hcd_to_hc(hcd);
     85        return hc_start(hc, hcd->irq_cap >= 0);
     86}
     87
     88static int hcd_hc_gone(hc_device_t *hcd)
     89{
     90        xhci_hc_t *hc = hcd_to_hc(hcd);
     91        hc_fini(hc);
     92        return EOK;
     93}
     94
     95static const hc_driver_t xhci_driver = {
     96        .name = NAME,
     97        .hc_device_size = sizeof(xhci_hc_t),
     98
     99        .hc_add = hcd_hc_add,
    61100        .irq_code_gen = hcd_irq_code_gen,
    62101        .claim = hcd_claim,
    63102        .start = hcd_start,
    64         .setup_root_hub = NULL,
    65         .fini = hc_driver_fini,
    66         .ops = {
    67                 .schedule       = hcd_schedule,
    68                 .irq_hook       = hcd_interrupt,
    69                 .status_hook    = hcd_status,
    70         }
     103        .hc_gone = hcd_hc_gone,
    71104};
    72 
    73 static int hc_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *hw_res, ddf_dev_t *device)
    74 {
    75         int err;
    76 
    77         xhci_hc_t *hc = malloc(sizeof(xhci_hc_t));
    78         if (!hc)
    79                 return ENOMEM;
    80 
    81         if ((err = hc_init_mmio(hc, hw_res)))
    82                 goto err;
    83 
    84         hc->hcd = hcd;
    85 
    86         if ((err = hc_init_memory(hc, device)))
    87                 goto err;
    88 
    89         hcd_set_implementation(hcd, hc, &xhci_ddf_hc_driver.ops, &hc->bus.base);
    90 
    91         return EOK;
    92 err:
    93         free(hc);
    94         return err;
    95 }
    96 
    97 static int hcd_irq_code_gen(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
    98 {
    99         xhci_hc_t *hc = hcd_get_driver_data(hcd);
    100         assert(hc);
    101 
    102         return hc_irq_code_gen(code, hc, hw_res);
    103 }
    104 
    105 static int hcd_claim(hcd_t *hcd, ddf_dev_t *dev)
    106 {
    107         xhci_hc_t *hc = hcd_get_driver_data(hcd);
    108         assert(hc);
    109 
    110         return hc_claim(hc, dev);
    111 }
    112 
    113 static int hcd_start(hcd_t *hcd, bool irq)
    114 {
    115         xhci_hc_t *hc = hcd_get_driver_data(hcd);
    116         assert(hc);
    117 
    118         return hc_start(hc, irq);
    119 }
    120 
    121 static int hcd_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    122 {
    123         xhci_hc_t *hc = hcd_get_driver_data(hcd);
    124         assert(hc);
    125 
    126         return hc_schedule(hc, batch);
    127 }
    128 
    129 static int hcd_status(hcd_t *hcd, uint32_t *status)
    130 {
    131         xhci_hc_t *hc = hcd_get_driver_data(hcd);
    132         assert(hc);
    133         assert(status);
    134 
    135         return hc_status(hc, status);
    136 }
    137 
    138 static void hcd_interrupt(hcd_t *hcd, uint32_t status)
    139 {
    140         xhci_hc_t *hc = hcd_get_driver_data(hcd);
    141         assert(hc);
    142 
    143         hc_interrupt(hc, status);
    144 }
    145 
    146 static void hc_driver_fini(hcd_t *hcd)
    147 {
    148         xhci_hc_t *hc = hcd_get_driver_data(hcd);
    149         assert(hc);
    150 
    151         hc_fini(hc);
    152 
    153         free(hc);
    154 }
    155 
    156 /** Initializes a new ddf driver instance of XHCI hcd.
    157  *
    158  * @param[in] device DDF instance of the device to initialize.
    159  * @return Error code.
    160  */
    161 static int xhci_dev_add(ddf_dev_t *device)
    162 {
    163         usb_log_info("Adding device %s", ddf_dev_get_name(device));
    164         return hcd_ddf_add_hc(device, &xhci_ddf_hc_driver);
    165 }
    166 
    167 static int xhci_fun_online(ddf_fun_t *fun)
    168 {
    169         return hcd_ddf_device_online(fun);
    170 }
    171 
    172 static int xhci_fun_offline(ddf_fun_t *fun)
    173 {
    174         return hcd_ddf_device_offline(fun);
    175 }
    176 
    177 
    178 static const driver_ops_t xhci_driver_ops = {
    179         .dev_add = xhci_dev_add,
    180         .fun_online = xhci_fun_online,
    181         .fun_offline = xhci_fun_offline
    182 };
    183 
    184 static const driver_t xhci_driver = {
    185         .name = NAME,
    186         .driver_ops = &xhci_driver_ops
    187 };
    188 
    189105
    190106/** Initializes global driver structures (NONE).
     
    200116        log_init(NAME);
    201117        logctl_set_log_level(NAME, LVL_DEBUG2);
    202         return ddf_driver_main(&xhci_driver);
     118        return hc_driver_main(&xhci_driver);
    203119}
    204120
  • uspace/drv/bus/usb/xhci/rh.c

    r1ea0bbf r32fb6bce  
    9494        xhci_bus_t *bus = &rh->hc->bus;
    9595
    96         device_t *dev = hcd_ddf_device_create(rh->hc_device, &bus->base);
     96        device_t *dev = hcd_ddf_fun_create(&rh->hc->base);
    9797        if (!dev) {
    9898                usb_log_error("Failed to create USB device function.");
     
    132132
    133133err_usb_dev:
    134         hcd_ddf_device_destroy(dev);
     134        hcd_ddf_fun_destroy(dev);
    135135        return err;
    136136}
  • uspace/lib/usbhost/include/usb/host/bus.h

    r1ea0bbf r32fb6bce  
    4343#define LIBUSBHOST_HOST_BUS_H
    4444
    45 #include <usb/usb.h>
    46 #include <usb/request.h>
    47 #include <usb/host/hcd.h>
    48 
    4945#include <assert.h>
    5046#include <fibril_synch.h>
    5147#include <stdbool.h>
     48#include <usb/host/hcd.h>
     49#include <usb/request.h>
     50#include <usb/usb.h>
     51#include <usbhc_iface.h>
    5252
    5353typedef struct hcd hcd_t;
     
    9494
    9595        /* Global operations on the bus */
     96        void (*interrupt)(bus_t *, uint32_t);
     97        int (*status)(bus_t *, uint32_t *);
    9698        int (*reserve_default_address)(bus_t *, usb_speed_t);
    9799        int (*release_default_address)(bus_t *);
     
    116118
    117119        /* Operations on batch */
    118         void (*batch_destroy)(usb_transfer_batch_t *);  /**< Optional */
     120        void (*batch_destroy)(usb_transfer_batch_t *);          /**< Optional */
     121        int (*batch_schedule)(usb_transfer_batch_t *);
    119122};
    120123
     
    129132        fibril_mutex_t guard;
    130133
    131         /* TODO: get rid of this one. */
    132         hcd_t *hcd;
    133 
     134        /* Size of the device_t extended structure */
    134135        size_t device_size;
    135136
     
    140141} bus_t;
    141142
    142 void bus_init(bus_t *, hcd_t *, size_t);
     143void bus_init(bus_t *, size_t);
    143144int bus_device_init(device_t *, bus_t *);
    144145
     
    150151int bus_device_online(device_t *);
    151152int bus_device_offline(device_t *);
     153
     154int bus_device_send_batch(device_t *, usb_target_t,
     155    usb_direction_t direction, char *, size_t, uint64_t,
     156    usbhc_iface_transfer_callback_t, void *, const char *);
     157
     158ssize_t bus_device_send_batch_sync(device_t *, usb_target_t,
     159    usb_direction_t direction, char *, size_t, uint64_t,
     160    const char *);
    152161
    153162int bus_endpoint_add(device_t *, const usb_endpoint_desc_t *, endpoint_t **);
  • uspace/lib/usbhost/include/usb/host/ddf_helpers.h

    r1ea0bbf r32fb6bce  
    3939#include <ddf/driver.h>
    4040#include <ddf/interrupt.h>
    41 #include <device/hw_res_parsed.h>
    4241#include <usb/usb.h>
    4342
    4443#include <usb/host/hcd.h>
    4544
    46 typedef int (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *);
    47 typedef int (*irq_code_gen_t)(irq_code_t *, hcd_t *, const hw_res_list_parsed_t *);
    48 typedef int (*claim_t)(hcd_t *, ddf_dev_t *);
    49 typedef int (*driver_start_t)(hcd_t *, bool irq);
    50 typedef int (*setup_root_hub_t)(hcd_t *, ddf_dev_t *);
     45int hcd_ddf_setup_hc(ddf_dev_t *, size_t);
     46void hcd_ddf_clean_hc(hc_device_t *);
    5147
    52 typedef void (*driver_stop_t)(hcd_t *);
    53 typedef void (*driver_fini_t)(hcd_t *);
     48int hcd_setup_virtual_root_hub(hc_device_t *);
    5449
    55 /**
    56  * All callbacks are optional.
    57  */
    58 typedef struct {
    59         hcd_ops_t ops;
    60         const char *name;
     50device_t *hcd_ddf_fun_create(hc_device_t *);
     51void hcd_ddf_fun_destroy(device_t *);
    6152
    62         interrupt_handler_t *irq_handler;  /**< Handler of IRQ. Do have generic implementation. */
     53int hcd_device_explore(device_t *);
    6354
    64         /* Initialization sequence: */
    65         driver_init_t init;                /**< Initialize internal structures, memory */
    66         claim_t claim;                     /**< Claim device from BIOS */
    67         irq_code_gen_t irq_code_gen;       /**< Generate IRQ handling code */
    68         driver_start_t start;              /**< Start the HC */
    69         setup_root_hub_t setup_root_hub;   /**< Setup the root hub */
     55int hcd_ddf_enable_interrupt(hc_device_t *hcd, int);
     56int hcd_ddf_get_registers(hc_device_t *hcd, hw_res_list_parsed_t *hw_res);
    7057
    71         /* Destruction sequence: */
    72         driver_stop_t stop;                /**< Stop the HC (counterpart of start) */
    73         driver_fini_t fini;                /**< Destroy internal structures (counterpart of init) */
    74 } ddf_hc_driver_t;
    75 
    76 int hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver);
    77 
    78 int hcd_ddf_setup_hc(ddf_dev_t *device);
    79 void hcd_ddf_clean_hc(ddf_dev_t *device);
    80 
    81 int hcd_setup_virtual_root_hub(hcd_t *, ddf_dev_t *);
    82 
    83 device_t *hcd_ddf_device_create(ddf_dev_t *, bus_t *);
    84 void hcd_ddf_device_destroy(device_t *);
    85 int hcd_ddf_device_explore(device_t *);
    86 int hcd_ddf_device_online(ddf_fun_t *);
    87 int hcd_ddf_device_offline(ddf_fun_t *);
    88 
    89 hcd_t *dev_to_hcd(ddf_dev_t *dev);
    90 
    91 int hcd_ddf_enable_interrupt(ddf_dev_t *device, int);
    92 int hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res);
    93 int hcd_ddf_setup_interrupts(ddf_dev_t *device,
    94     const hw_res_list_parsed_t *hw_res,
    95     interrupt_handler_t handler,
    96     irq_code_gen_t gen_irq_code);
    97 void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev);
     58void hcd_ddf_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev);
    9859
    9960#endif
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    r1ea0bbf r32fb6bce  
    109109ssize_t endpoint_count_bw(endpoint_t *, size_t);
    110110
     111int endpoint_send_batch(endpoint_t *, usb_target_t, usb_direction_t,
     112    char *, size_t, uint64_t, usbhc_iface_transfer_callback_t, void *,
     113    const char *);
     114
    111115static inline bus_t *endpoint_get_bus(endpoint_t *ep)
    112116{
  • uspace/lib/usbhost/include/usb/host/hcd.h

    r1ea0bbf r32fb6bce  
    3737#define LIBUSBHOST_HOST_HCD_H
    3838
    39 #include <assert.h>
    40 #include <mem.h>
    41 #include <stddef.h>
    42 #include <stdint.h>
    43 #include <usb/usb.h>
    44 #include <usbhc_iface.h>
     39#include <ddf/driver.h>
     40#include <usb/request.h>
    4541
    46 typedef struct hcd hcd_t;
     42typedef struct hw_resource_list_parsed hw_res_list_parsed_t;
    4743typedef struct bus bus_t;
    4844typedef struct device device_t;
    49 typedef struct usb_transfer_batch usb_transfer_batch_t;
    5045
    51 typedef int (*schedule_hook_t)(hcd_t *, usb_transfer_batch_t *);
    52 typedef void (*interrupt_hook_t)(hcd_t *, uint32_t);
    53 typedef int (*status_hook_t)(hcd_t *, uint32_t *);
     46/* Treat this header as read-only in driver code.
     47 * It could be opaque, but why to complicate matters.
     48 */
     49typedef struct hc_device {
     50        /* Bus instance */
     51        bus_t *bus;
    5452
    55 typedef struct {
    56         /** Transfer scheduling, implement in device driver. */
    57         schedule_hook_t schedule;
    58         /** Hook to be called on device interrupt, passes ARG1 */
    59         interrupt_hook_t irq_hook;
    60         /** Periodic polling hook */
    61         status_hook_t status_hook;
    62 } hcd_ops_t;
     53        /* Managed DDF device */
     54        ddf_dev_t *ddf_dev;
    6355
    64 /** Generic host controller driver structure. */
    65 struct hcd {
    66         /** Endpoint manager. */
    67         bus_t *bus;
     56        /* Control function */
     57        ddf_fun_t *ctl_fun;
     58
     59        /* Result of enabling HW IRQs */
     60        int irq_cap;
    6861
    6962        /** Interrupt replacement fibril */
    7063        fid_t polling_fibril;
    7164
    72         /** Driver implementation */
    73         hcd_ops_t ops;
     65        /* This structure is meant to be extended by driver code. */
     66} hc_device_t;
    7467
    75         /** Device specific driver data. */
    76         void * driver_data;
    77 };
     68typedef struct hc_driver {
     69        const char *name;
    7870
    79 extern void hcd_init(hcd_t *);
     71        /** Size of the device data to be allocated, and passed as the
     72         * hc_device_t. */
     73        size_t hc_device_size;
    8074
    81 static inline void hcd_set_implementation(hcd_t *hcd, void *data,
    82     const hcd_ops_t *ops, bus_t *bus)
    83 {
    84         assert(hcd);
    85         if (ops) {
    86                 hcd->driver_data = data;
    87                 hcd->ops = *ops;
    88                 hcd->bus = bus;
    89         } else {
    90                 memset(&hcd->ops, 0, sizeof(hcd->ops));
    91         }
     75        /** Initialize device structures. */
     76        int (*hc_add)(hc_device_t *, const hw_res_list_parsed_t *);
     77
     78        /** Generate IRQ code to handle interrupts. */
     79        int (*irq_code_gen)(irq_code_t *, hc_device_t *, const hw_res_list_parsed_t *);
     80
     81        /** Claim device from BIOS. */
     82        int (*claim)(hc_device_t *);
     83
     84        /** Start the host controller. */
     85        int (*start)(hc_device_t *);
     86
     87        /** Setup the virtual roothub. */
     88        int (*setup_root_hub)(hc_device_t *);
     89
     90        /** Stop the host controller (after start has been called) */
     91        int (*stop)(hc_device_t *);
     92
     93        /** HC was asked to be removed (after hc_add has been called) */
     94        int (*hc_remove)(hc_device_t *);
     95
     96        /** HC is gone. */
     97        int (*hc_gone)(hc_device_t *);
     98} hc_driver_t;
     99
     100/* Drivers should call this before leaving hc_add */
     101static inline void hc_device_setup(hc_device_t *hcd, bus_t *bus) {
     102        hcd->bus = bus;
    92103}
    93104
    94 static inline void * hcd_get_driver_data(hcd_t *hcd)
     105static inline hc_device_t *dev_to_hcd(ddf_dev_t *dev)
    95106{
    96         assert(hcd);
    97         return hcd->driver_data;
     107        return ddf_dev_data_get(dev);
    98108}
    99109
    100 extern int hcd_get_ep0_max_packet_size(uint16_t *, hcd_t *, device_t *);
     110int hc_driver_main(const hc_driver_t *);
     111
     112/* TODO: These are a kind of utility functions, they should probably go
     113 * somewhere else.
     114 */
     115extern int hcd_get_ep0_max_packet_size(uint16_t *, bus_t *, device_t *);
    101116extern void hcd_setup_device_tt(device_t *);
    102 
    103 extern int hcd_send_batch(hcd_t *, device_t *, usb_target_t,
    104     usb_direction_t direction, char *, size_t, uint64_t,
    105     usbhc_iface_transfer_callback_t, void *, const char *);
    106 
    107 extern ssize_t hcd_send_batch_sync(hcd_t *, device_t *, usb_target_t,
    108     usb_direction_t direction, char *, size_t, uint64_t,
    109     const char *);
    110117
    111118/** How many toggles need to be reset */
     
    116123} toggle_reset_mode_t;
    117124
     125extern toggle_reset_mode_t hcd_get_request_toggle_reset_mode(
     126    const usb_device_request_setup_packet_t *request);
     127
    118128#endif
    119129
  • uspace/lib/usbhost/include/usb/host/usb2_bus.h

    r1ea0bbf r32fb6bce  
    6666extern const bus_ops_t usb2_bus_ops;
    6767
    68 extern int usb2_bus_init(usb2_bus_t *, hcd_t *, size_t);
     68extern int usb2_bus_init(usb2_bus_t *, size_t);
    6969
    7070#endif
  • uspace/lib/usbhost/src/bus.c

    r1ea0bbf r32fb6bce  
    4646 * Initializes the bus structure.
    4747 */
    48 void bus_init(bus_t *bus, hcd_t *hcd, size_t device_size)
    49 {
    50         assert(bus);
    51         assert(hcd);
     48void bus_init(bus_t *bus, size_t device_size)
     49{
     50        assert(bus);
    5251        assert(device_size >= sizeof(device_t));
    5352        memset(bus, 0, sizeof(bus_t));
    5453
    5554        fibril_mutex_initialize(&bus->guard);
    56         bus->hcd = hcd;
    5755        bus->device_size = device_size;
    5856}
     
    6159{
    6260        assert(bus);
    63         assert(bus->hcd);
    6461
    6562        memset(dev, 0, sizeof(*dev));
     
    258255}
    259256
     257/** Prepare generic usb_transfer_batch and schedule it.
     258 * @param device Device for which to send the batch
     259 * @param target address and endpoint number.
     260 * @param setup_data Data to use in setup stage (Control communication type)
     261 * @param in Callback for device to host communication.
     262 * @param out Callback for host to device communication.
     263 * @param arg Callback parameter.
     264 * @param name Communication identifier (for nicer output).
     265 * @return Error code.
     266 */
     267int bus_device_send_batch(device_t *device, usb_target_t target,
     268    usb_direction_t direction, char *data, size_t size, uint64_t setup_data,
     269    usbhc_iface_transfer_callback_t on_complete, void *arg, const char *name)
     270{
     271        assert(device->address == target.address);
     272
     273        /* Temporary reference */
     274        endpoint_t *ep = bus_find_endpoint(device, target, direction);
     275        if (ep == NULL) {
     276                usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
     277                    device->address, target.endpoint, name);
     278                return ENOENT;
     279        }
     280
     281        assert(ep->device == device);
     282
     283        const int err = endpoint_send_batch(ep, target, direction, data, size, setup_data,
     284            on_complete, arg, name);
     285
     286        /* Temporary reference */
     287        endpoint_del_ref(ep);
     288
     289        return err;
     290}
     291
     292typedef struct {
     293        fibril_mutex_t done_mtx;
     294        fibril_condvar_t done_cv;
     295        unsigned done;
     296
     297        size_t transfered_size;
     298        int error;
     299} sync_data_t;
     300
     301static int sync_transfer_complete(void *arg, int error, size_t transfered_size)
     302{
     303        sync_data_t *d = arg;
     304        assert(d);
     305        d->transfered_size = transfered_size;
     306        d->error = error;
     307        fibril_mutex_lock(&d->done_mtx);
     308        d->done = 1;
     309        fibril_condvar_broadcast(&d->done_cv);
     310        fibril_mutex_unlock(&d->done_mtx);
     311        return EOK;
     312}
     313
     314ssize_t bus_device_send_batch_sync(device_t *device, usb_target_t target,
     315    usb_direction_t direction, char *data, size_t size, uint64_t setup_data,
     316    const char *name)
     317{
     318        sync_data_t sd = { .done = 0 };
     319        fibril_mutex_initialize(&sd.done_mtx);
     320        fibril_condvar_initialize(&sd.done_cv);
     321
     322        const int ret = bus_device_send_batch(device, target, direction,
     323            data, size, setup_data,
     324            sync_transfer_complete, &sd, name);
     325        if (ret != EOK)
     326                return ret;
     327
     328        fibril_mutex_lock(&sd.done_mtx);
     329        while (!sd.done) {
     330                fibril_condvar_wait_timeout(&sd.done_cv, &sd.done_mtx, 3000000);
     331                if (!sd.done)
     332                        usb_log_debug2("Still waiting...");
     333        }
     334        fibril_mutex_unlock(&sd.done_mtx);
     335
     336        return (sd.error == EOK)
     337                ? (ssize_t) sd.transfered_size
     338                : (ssize_t) sd.error;
     339}
     340
    260341/**
    261342 * @}
  • uspace/lib/usbhost/src/ddf_helpers.c

    r1ea0bbf r32fb6bce  
    5353#include "ddf_helpers.h"
    5454
    55 typedef struct hc_dev {
    56         ddf_fun_t *ctl_fun;
    57         hcd_t hcd;
    58 } hc_dev_t;
    59 
    60 static hc_dev_t *dev_to_hc_dev(ddf_dev_t *dev)
    61 {
    62         return ddf_dev_data_get(dev);
    63 }
    64 
    65 hcd_t *dev_to_hcd(ddf_dev_t *dev)
    66 {
    67         hc_dev_t *hc_dev = dev_to_hc_dev(dev);
    68         if (!hc_dev) {
    69                 usb_log_error("Invalid HCD device.\n");
    70                 return NULL;
    71         }
    72         return &hc_dev->hcd;
    73 }
    74 
    75 
    76 static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub_dev, unsigned port);
     55
     56static int hcd_ddf_new_device(hc_device_t *hcd, ddf_dev_t *hc, device_t *hub_dev, unsigned port);
    7757static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub, unsigned port);
    7858
     
    8969{
    9070        assert(fun);
    91         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     71        hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    9272        device_t *dev = ddf_fun_data_get(fun);
    9373        assert(hcd);
     
    11393{
    11494        assert(fun);
    115         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     95        hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    11696        device_t *dev = ddf_fun_data_get(fun);
    11797        assert(hcd);
     
    138118{
    139119        assert(fun);
    140         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     120        hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    141121        device_t *dev = ddf_fun_data_get(fun);
    142122        assert(hcd);
     
    152132{
    153133        assert(fun);
    154         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
     134        hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    155135        device_t *dev = ddf_fun_data_get(fun);
    156136        assert(hcd);
     
    167147        ddf_dev_t *hc = ddf_fun_get_dev(fun);
    168148        assert(hc);
    169         hcd_t *hcd = dev_to_hcd(hc);
     149        hc_device_t *hcd = dev_to_hcd(hc);
    170150        assert(hcd);
    171151        device_t *hub = ddf_fun_data_get(fun);
     
    218198{
    219199        assert(fun);
    220         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    221200        device_t *dev = ddf_fun_data_get(fun);
    222201        assert(dev);
     
    224203        target.address = dev->address;
    225204
    226         return hcd_send_batch(hcd, dev, target, USB_DIRECTION_IN,
     205        return bus_device_send_batch(dev, target, USB_DIRECTION_IN,
    227206            data, size, setup_data,
    228207            callback, arg, "READ");
     
    244223{
    245224        assert(fun);
    246         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    247225        device_t *dev = ddf_fun_data_get(fun);
    248226        assert(dev);
     
    250228        target.address = dev->address;
    251229
    252         return hcd_send_batch(hcd, dev, target, USB_DIRECTION_OUT,
     230        return bus_device_send_batch(dev, target, USB_DIRECTION_OUT,
    253231            (char *) data, size, setup_data,
    254232            callback, arg, "WRITE");
     
    337315        assert(device);
    338316
    339         hcd_t *hcd = dev_to_hcd(device);
     317        hc_device_t *hcd = dev_to_hcd(device);
    340318        assert(hcd);
    341319        assert(hcd->bus);
    342 
    343         hc_dev_t *hc_dev = dev_to_hc_dev(device);
    344         assert(hc_dev);
    345320
    346321        fibril_mutex_lock(&hub->guard);
     
    374349}
    375350
    376 device_t *hcd_ddf_device_create(ddf_dev_t *hc, bus_t *bus)
     351device_t *hcd_ddf_fun_create(hc_device_t *hc)
    377352{
    378353        /* Create DDF function for the new device */
    379         ddf_fun_t *fun = ddf_fun_create(hc, fun_inner, NULL);
     354        ddf_fun_t *fun = ddf_fun_create(hc->ddf_dev, fun_inner, NULL);
    380355        if (!fun)
    381356                return NULL;
     
    384359
    385360        /* Create USB device node for the new device */
    386         device_t *dev = ddf_fun_data_alloc(fun, bus->device_size);
     361        device_t *dev = ddf_fun_data_alloc(fun, hc->bus->device_size);
    387362        if (!dev) {
    388363                ddf_fun_destroy(fun);
     
    390365        }
    391366
    392         bus_device_init(dev, bus);
     367        bus_device_init(dev, hc->bus);
    393368        dev->fun = fun;
    394369        return dev;
    395370}
    396371
    397 void hcd_ddf_device_destroy(device_t *dev)
     372void hcd_ddf_fun_destroy(device_t *dev)
    398373{
    399374        assert(dev);
     
    402377}
    403378
    404 int hcd_ddf_device_explore(device_t *device)
     379int hcd_device_explore(device_t *device)
    405380{
    406381        int err;
     
    421396        usb_log_debug("Device(%d): Requesting full device descriptor.",
    422397            device->address);
    423         ssize_t got = hcd_send_batch_sync(device->bus->hcd, device, control_ep, USB_DIRECTION_IN,
     398        ssize_t got = bus_device_send_batch_sync(device, control_ep, USB_DIRECTION_IN,
    424399            (char *) &desc, sizeof(desc), *(uint64_t *)&get_device_desc,
    425400            "read device descriptor");
     
    447422}
    448423
    449 int hcd_ddf_device_online(ddf_fun_t *fun)
    450 {
    451         assert(fun);
    452 
    453         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    454         device_t *dev = ddf_fun_data_get(fun);
    455         assert(dev);
    456         assert(hcd->bus);
    457 
    458         usb_log_info("Device(%d): Requested to be brought online.", dev->address);
    459 
    460         return bus_device_online(dev);
    461 }
    462 
    463 int hcd_ddf_device_offline(ddf_fun_t *fun)
    464 {
    465         assert(fun);
    466 
    467         hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
    468         device_t *dev = ddf_fun_data_get(fun);
    469         assert(dev);
    470         assert(hcd->bus);
    471 
    472         usb_log_info("Device(%d): Requested to be taken offline.", dev->address);
    473 
    474         return bus_device_offline(dev);
    475 }
    476 
    477 static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub, unsigned port)
     424static int hcd_ddf_new_device(hc_device_t *hcd, ddf_dev_t *hc, device_t *hub, unsigned port)
    478425{
    479426        int err;
     
    483430        assert(hc);
    484431
    485         device_t *dev = hcd_ddf_device_create(hc, hcd->bus);
     432        device_t *dev = hcd_ddf_fun_create(hcd);
    486433        if (!dev) {
    487434                usb_log_error("Failed to create USB device function.");
     
    516463
    517464err_usb_dev:
    518         hcd_ddf_device_destroy(dev);
     465        hcd_ddf_fun_destroy(dev);
    519466        return err;
    520467}
     
    525472 * @return Error code
    526473 */
    527 int hcd_setup_virtual_root_hub(hcd_t *hcd, ddf_dev_t *hc)
     474int hcd_setup_virtual_root_hub(hc_device_t *hcd)
    528475{
    529476        int err;
    530477
    531         assert(hc);
    532         assert(hcd);
    533         assert(hcd->bus);
     478        assert(hcd);
    534479
    535480        if ((err = bus_reserve_default_address(hcd->bus, USB_SPEED_MAX))) {
     
    538483        }
    539484
    540         device_t *dev = hcd_ddf_device_create(hc, hcd->bus);
     485        device_t *dev = hcd_ddf_fun_create(hcd);
    541486        if (!dev) {
    542487                usb_log_error("Failed to create function for the root hub.");
     
    561506
    562507err_usb_dev:
    563         hcd_ddf_device_destroy(dev);
     508        hcd_ddf_fun_destroy(dev);
    564509err_default_address:
    565510        bus_release_default_address(hcd->bus);
     
    577522 * This function does all the ddf work for hc driver.
    578523 */
    579 int hcd_ddf_setup_hc(ddf_dev_t *device)
     524int hcd_ddf_setup_hc(ddf_dev_t *device, size_t size)
    580525{
    581526        assert(device);
    582527
    583         hc_dev_t *instance = ddf_dev_data_alloc(device, sizeof(hc_dev_t));
     528        hc_device_t *instance = ddf_dev_data_alloc(device, size);
    584529        if (instance == NULL) {
    585530                usb_log_error("Failed to allocate HCD ddf structure.\n");
    586531                return ENOMEM;
    587532        }
    588         hcd_init(&instance->hcd);
     533        instance->ddf_dev = device;
    589534
    590535        int ret = ENOMEM;
     
    618563}
    619564
    620 void hcd_ddf_clean_hc(ddf_dev_t *device)
    621 {
    622         assert(device);
    623         hc_dev_t *hc = dev_to_hc_dev(device);
    624         assert(hc);
    625         const int ret = ddf_fun_unbind(hc->ctl_fun);
    626         if (ret == EOK)
    627                 ddf_fun_destroy(hc->ctl_fun);
    628 }
    629 
    630 //TODO: Cache parent session in HCD
     565void hcd_ddf_clean_hc(hc_device_t *hcd)
     566{
     567        if (ddf_fun_unbind(hcd->ctl_fun) == EOK)
     568                ddf_fun_destroy(hcd->ctl_fun);
     569}
     570
    631571/** Call the parent driver with a request to enable interrupt
    632572 *
     
    635575 * @return Error code.
    636576 */
    637 int hcd_ddf_enable_interrupt(ddf_dev_t *device, int inum)
    638 {
    639         async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
     577int hcd_ddf_enable_interrupt(hc_device_t *hcd, int inum)
     578{
     579        async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev);
    640580        if (parent_sess == NULL)
    641581                return EIO;
     
    644584}
    645585
    646 //TODO: Cache parent session in HCD
    647 int hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res)
    648 {
    649         async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
     586int hcd_ddf_get_registers(hc_device_t *hcd, hw_res_list_parsed_t *hw_res)
     587{
     588        async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev);
    650589        if (parent_sess == NULL)
    651590                return EIO;
     
    658597}
    659598
    660 // TODO: move this someplace else
    661 static inline void irq_code_clean(irq_code_t *code)
    662 {
    663         if (code) {
    664                 free(code->ranges);
    665                 free(code->cmds);
    666                 code->ranges = NULL;
    667                 code->cmds = NULL;
    668                 code->rangecount = 0;
    669                 code->cmdcount = 0;
    670         }
    671 }
    672 
    673 /** Register interrupt handler
    674  *
    675  * @param[in] device Host controller DDF device
    676  * @param[in] regs Register range
    677  * @param[in] irq Interrupt number
    678  * @paran[in] handler Interrupt handler
    679  * @param[in] gen_irq_code IRQ code generator.
    680  *
    681  * @return IRQ capability handle on success.
    682  * @return Negative error code.
    683  */
    684 int hcd_ddf_setup_interrupts(ddf_dev_t *device,
    685     const hw_res_list_parsed_t *hw_res,
    686     interrupt_handler_t handler,
    687     irq_code_gen_t gen_irq_code)
    688 {
    689         assert(device);
    690 
    691         hcd_t *hcd = dev_to_hcd(device);
    692 
    693         if (!handler || !gen_irq_code)
    694                 return ENOTSUP;
    695 
    696         irq_code_t irq_code = {0};
    697 
    698         const int irq = gen_irq_code(&irq_code, hcd, hw_res);
    699         if (irq < 0) {
    700                 usb_log_error("Failed to generate IRQ code: %s.\n",
    701                     str_error(irq));
    702                 return irq;
    703         }
    704 
    705         /* Register handler to avoid interrupt lockup */
    706         const int irq_cap = register_interrupt_handler(device, irq, handler,
    707             &irq_code);
    708         irq_code_clean(&irq_code);
    709         if (irq_cap < 0) {
    710                 usb_log_error("Failed to register interrupt handler: %s.\n",
    711                     str_error(irq_cap));
    712                 return irq_cap;
    713         }
    714 
    715         /* Enable interrupts */
    716         int ret = hcd_ddf_enable_interrupt(device, irq);
    717         if (ret != EOK) {
    718                 usb_log_error("Failed to enable interrupts: %s.\n",
    719                     str_error(ret));
    720                 unregister_interrupt_handler(device, irq_cap);
    721                 return ret;
    722         }
    723         return irq_cap;
    724 }
    725 
    726 /** IRQ handling callback, forward status from call to diver structure.
    727  *
    728  * @param[in] dev DDF instance of the device to use.
    729  * @param[in] iid (Unused).
    730  * @param[in] call Pointer to the call from kernel.
    731  */
    732 void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev)
    733 {
    734         assert(dev);
    735         hcd_t *hcd = dev_to_hcd(dev);
    736         if (!hcd || !hcd->ops.irq_hook) {
    737                 usb_log_error("Interrupt on not yet initialized device.\n");
    738                 return;
    739         }
    740         const uint32_t status = IPC_GET_ARG1(*call);
    741         hcd->ops.irq_hook(hcd, status);
    742 }
    743 
    744 static int interrupt_polling(void *arg)
    745 {
    746         hcd_t *hcd = arg;
    747         assert(hcd);
    748         if (!hcd->ops.status_hook || !hcd->ops.irq_hook)
    749                 return ENOTSUP;
    750         uint32_t status = 0;
    751         while (hcd->ops.status_hook(hcd, &status) == EOK) {
    752                 hcd->ops.irq_hook(hcd, status);
    753                 status = 0;
    754                 /* We should wait 1 frame - 1ms here, but this polling is a
    755                  * lame crutch anyway so don't hog the system. 10ms is still
    756                  * good enough for emergency mode */
    757                 async_usleep(10000);
    758         }
    759         return EOK;
    760 }
    761 
    762 /** Initialize hc and rh DDF structures and their respective drivers.
    763  *
    764  * @param device DDF instance of the device to use
    765  * @param speed Maximum supported speed
    766  * @param bw Available bandwidth (arbitrary units)
    767  * @param bw_count Bandwidth computing function
    768  * @param irq_handler IRQ handling function
    769  * @param gen_irq_code Function to generate IRQ pseudocode
    770  *                     (it needs to return used irq number)
    771  * @param driver_init Function to initialize HC driver
    772  * @param driver_fini Function to cleanup HC driver
    773  * @return Error code
    774  *
    775  * This function does all the preparatory work for hc and rh drivers:
    776  *  - gets device's hw resources
    777  *  - attempts to enable interrupts
    778  *  - registers interrupt handler
    779  *  - calls driver specific initialization
    780  *  - registers root hub
    781  */
    782 int hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver)
    783 {
    784         assert(driver);
    785 
    786         int ret = EOK;
    787 
    788         hw_res_list_parsed_t hw_res;
    789         ret = hcd_ddf_get_registers(device, &hw_res);
    790         if (ret != EOK) {
    791                 usb_log_error("Failed to get register memory addresses "
    792                     "for `%s': %s.\n", ddf_dev_get_name(device),
    793                     str_error(ret));
    794                 return ret;
    795         }
    796 
    797         ret = hcd_ddf_setup_hc(device);
    798         if (ret != EOK) {
    799                 usb_log_error("Failed to setup generic HCD.\n");
    800                 goto err_hw_res;
    801         }
    802 
    803         hcd_t *hcd = dev_to_hcd(device);
    804 
    805         if (driver->init)
    806                 ret = driver->init(hcd, &hw_res, device);
    807         if (ret != EOK) {
    808                 usb_log_error("Failed to init HCD.\n");
    809                 goto err_hcd;
    810         }
    811 
    812         /* Setup interrupts  */
    813         interrupt_handler_t *irq_handler =
    814             driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler;
    815         const int irq_cap = hcd_ddf_setup_interrupts(device, &hw_res,
    816             irq_handler, driver->irq_code_gen);
    817         bool irqs_enabled = !(irq_cap < 0);
    818         if (irqs_enabled) {
    819                 usb_log_debug("Hw interrupts enabled.\n");
    820         }
    821 
    822         /* Claim the device from BIOS */
    823         if (driver->claim)
    824                 ret = driver->claim(hcd, device);
    825         if (ret != EOK) {
    826                 usb_log_error("Failed to claim `%s' for driver `%s': %s",
    827                     ddf_dev_get_name(device), driver->name, str_error(ret));
    828                 goto err_irq;
    829         }
    830 
    831         /* Start hw driver */
    832         if (driver->start)
    833                 ret = driver->start(hcd, irqs_enabled);
    834         if (ret != EOK) {
    835                 usb_log_error("Failed to start HCD: %s.\n", str_error(ret));
    836                 goto err_irq;
    837         }
    838 
    839         /* Need working irq replacement to setup root hub */
    840         if (!irqs_enabled && hcd->ops.status_hook) {
    841                 hcd->polling_fibril = fibril_create(interrupt_polling, hcd);
    842                 if (hcd->polling_fibril == 0) {
    843                         usb_log_error("Failed to create polling fibril\n");
    844                         ret = ENOMEM;
    845                         goto err_started;
    846                 }
    847                 fibril_add_ready(hcd->polling_fibril);
    848                 usb_log_warning("Failed to enable interrupts: %s."
    849                     " Falling back to polling.\n", str_error(irq_cap));
    850         }
    851 
    852         /*
    853          * Creating root hub registers a new USB device so HC
    854          * needs to be ready at this time.
    855          */
    856         if (driver->setup_root_hub)
    857                 ret = driver->setup_root_hub(hcd, device);
    858         if (ret != EOK) {
    859                 usb_log_error("Failed to setup HC root hub: %s.\n",
    860                     str_error(ret));
    861                 goto err_polling;
    862         }
    863 
    864         usb_log_info("Controlling new `%s' device `%s'.\n",
    865             driver->name, ddf_dev_get_name(device));
    866         return EOK;
    867 
    868 err_polling:
    869         // TODO: Stop the polling fibril (refactor the interrupt_polling func)
    870         //
    871 err_started:
    872         if (driver->stop)
    873                 driver->stop(hcd);
    874 err_irq:
    875         unregister_interrupt_handler(device, irq_cap);
    876         if (driver->fini)
    877                 driver->fini(hcd);
    878 err_hcd:
    879         hcd_ddf_clean_hc(device);
    880 err_hw_res:
    881         hw_res_list_parsed_clean(&hw_res);
    882         return ret;
    883 }
    884 
    885599/**
    886600 * @}
  • uspace/lib/usbhost/src/endpoint.c

    r1ea0bbf r32fb6bce  
    3939#include <mem.h>
    4040#include <stdlib.h>
     41#include <str_error.h>
     42#include <usb/debug.h>
     43#include <usb/host/hcd.h>
    4144
    4245#include "usb_transfer_batch.h"
     
    187190}
    188191
     192/** Prepare generic usb_transfer_batch and schedule it.
     193 * @param ep Endpoint for which the batch shall be created.
     194 * @param target address and endpoint number.
     195 * @param setup_data Data to use in setup stage (Control communication type)
     196 * @param in Callback for device to host communication.
     197 * @param out Callback for host to device communication.
     198 * @param arg Callback parameter.
     199 * @param name Communication identifier (for nicer output).
     200 * @return Error code.
     201 */
     202int endpoint_send_batch(endpoint_t *ep, usb_target_t target,
     203    usb_direction_t direction, char *data, size_t size, uint64_t setup_data,
     204    usbhc_iface_transfer_callback_t on_complete, void *arg, const char *name)
     205{
     206        usb_log_debug2("%s %d:%d %zu(%zu).\n",
     207            name, target.address, target.endpoint, size, ep->max_packet_size);
     208
     209        bus_t *bus = endpoint_get_bus(ep);
     210        const bus_ops_t *ops = BUS_OPS_LOOKUP(bus->ops, batch_schedule);
     211        if (!ops) {
     212                usb_log_error("HCD does not implement scheduler.\n");
     213                return ENOTSUP;
     214        }
     215
     216        const size_t bw = endpoint_count_bw(ep, size);
     217        /* Check if we have enough bandwidth reserved */
     218        if (ep->bandwidth < bw) {
     219                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
     220                    "but only %zu is reserved.\n",
     221                    ep->device->address, ep->endpoint, name, bw, ep->bandwidth);
     222                return ENOSPC;
     223        }
     224
     225        usb_transfer_batch_t *batch = usb_transfer_batch_create(ep);
     226        if (!batch) {
     227                usb_log_error("Failed to create transfer batch.\n");
     228                return ENOMEM;
     229        }
     230
     231        batch->target = target;
     232        batch->buffer = data;
     233        batch->buffer_size = size;
     234        batch->setup.packed = setup_data;
     235        batch->dir = direction;
     236        batch->on_complete = on_complete;
     237        batch->on_complete_data = arg;
     238
     239        /* Check for commands that reset toggle bit */
     240        if (ep->transfer_type == USB_TRANSFER_CONTROL)
     241                batch->toggle_reset_mode
     242                        = hcd_get_request_toggle_reset_mode(&batch->setup.packet);
     243
     244        const int ret = ops->batch_schedule(batch);
     245        if (ret != EOK) {
     246                usb_log_warning("Batch %p failed to schedule: %s", batch, str_error(ret));
     247                usb_transfer_batch_destroy(batch);
     248        }
     249
     250        return ret;
     251}
     252
    189253/**
    190254 * @}
  • uspace/lib/usbhost/src/hcd.c

    r1ea0bbf r32fb6bce  
    3636#include <assert.h>
    3737#include <async.h>
     38#include <ddf/interrupt.h>
    3839#include <errno.h>
    3940#include <macros.h>
     
    4546
    4647#include "bus.h"
     48#include "ddf_helpers.h"
    4749#include "endpoint.h"
    4850#include "usb_transfer_batch.h"
     
    5052#include "hcd.h"
    5153
    52 
    53 /** Initialize hcd_t structure.
    54  * Initializes device and endpoint managers. Sets data and hook pointer to NULL.
    55  *
    56  * @param hcd hcd_t structure to initialize, non-null.
    57  * @param max_speed Maximum supported USB speed (full, high).
    58  * @param bandwidth Available bandwidth, passed to endpoint manager.
    59  * @param bw_count Bandwidth compute function, passed to endpoint manager.
    60  */
    61 void hcd_init(hcd_t *hcd) {
     54int hc_dev_add(ddf_dev_t *);
     55int hc_dev_remove(ddf_dev_t *);
     56int hc_dev_gone(ddf_dev_t *);
     57int hc_fun_online(ddf_fun_t *);
     58int hc_fun_offline(ddf_fun_t *);
     59
     60static driver_ops_t hc_driver_ops = {
     61        .dev_add = hc_dev_add,
     62        .dev_remove = hc_dev_remove,
     63        .dev_gone = hc_dev_gone,
     64        .fun_online = hc_fun_offline,
     65        .fun_offline = hc_fun_offline,
     66};
     67
     68static const hc_driver_t *hc_driver;
     69
     70int hc_driver_main(const hc_driver_t *driver)
     71{
     72        driver_t ddf_driver = {
     73                .name = driver->name,
     74                .driver_ops = &hc_driver_ops,
     75        };
     76
     77        /* Remember ops to call. */
     78        hc_driver = driver;
     79
     80        return ddf_driver_main(&ddf_driver);
     81}
     82
     83/** IRQ handling callback, forward status from call to diver structure.
     84 *
     85 * @param[in] dev DDF instance of the device to use.
     86 * @param[in] iid (Unused).
     87 * @param[in] call Pointer to the call from kernel.
     88 */
     89static void irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev)
     90{
     91        assert(dev);
     92        hc_device_t *hcd = dev_to_hcd(dev);
     93
     94        const bus_ops_t *ops = BUS_OPS_LOOKUP(hcd->bus->ops, interrupt);
     95        assert(ops);
     96
     97        const uint32_t status = IPC_GET_ARG1(*call);
     98        ops->interrupt(hcd->bus, status);
     99}
     100
     101/** Worker for the HW interrupt replacement fibril.
     102 */
     103static int interrupt_polling(void *arg)
     104{
     105        hc_device_t *hcd = arg;
    62106        assert(hcd);
    63 
    64         hcd_set_implementation(hcd, NULL, NULL, NULL);
     107        bus_t *bus = hcd->bus;
     108
     109        const bus_ops_t *interrupt_ops = BUS_OPS_LOOKUP(bus->ops, interrupt);
     110        const bus_ops_t *status_ops = BUS_OPS_LOOKUP(bus->ops, status);
     111        if (!interrupt_ops || !status_ops)
     112                return ENOTSUP;
     113
     114        uint32_t status = 0;
     115        while (status_ops->status(bus, &status) == EOK) {
     116                interrupt_ops->interrupt(bus, status);
     117                status = 0;
     118                /* We should wait 1 frame - 1ms here, but this polling is a
     119                 * lame crutch anyway so don't hog the system. 10ms is still
     120                 * good enough for emergency mode */
     121                async_usleep(10000);
     122        }
     123        return EOK;
     124}
     125
     126static inline void irq_code_clean(irq_code_t *code)
     127{
     128        if (code) {
     129                free(code->ranges);
     130                free(code->cmds);
     131                code->ranges = NULL;
     132                code->cmds = NULL;
     133                code->rangecount = 0;
     134                code->cmdcount = 0;
     135        }
     136}
     137
     138/** Register interrupt handler
     139 *
     140 * @param[in] device Host controller DDF device
     141 * @param[in] regs Register range
     142 * @param[in] irq Interrupt number
     143 * @paran[in] handler Interrupt handler
     144 * @param[in] gen_irq_code IRQ code generator.
     145 *
     146 * @return IRQ capability handle on success.
     147 * @return Negative error code.
     148 */
     149static int hcd_ddf_setup_interrupts(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
     150{
     151        assert(hcd);
     152        irq_code_t irq_code = {0};
     153
     154        if (!hc_driver->irq_code_gen)
     155                return ENOTSUP;
     156
     157        const int irq = hc_driver->irq_code_gen(&irq_code, hcd, hw_res);
     158        if (irq < 0) {
     159                usb_log_error("Failed to generate IRQ code: %s.\n",
     160                    str_error(irq));
     161                return irq;
     162        }
     163
     164        /* Register handler to avoid interrupt lockup */
     165        const int irq_cap = register_interrupt_handler(hcd->ddf_dev, irq, irq_handler, &irq_code);
     166        irq_code_clean(&irq_code);
     167        if (irq_cap < 0) {
     168                usb_log_error("Failed to register interrupt handler: %s.\n",
     169                    str_error(irq_cap));
     170                return irq_cap;
     171        }
     172
     173        /* Enable interrupts */
     174        int ret = hcd_ddf_enable_interrupt(hcd, irq);
     175        if (ret != EOK) {
     176                usb_log_error("Failed to enable interrupts: %s.\n",
     177                    str_error(ret));
     178                unregister_interrupt_handler(hcd->ddf_dev, irq_cap);
     179                return ret;
     180        }
     181        return irq_cap;
     182}
     183
     184/** Initialize HC in memory of the driver.
     185 *
     186 * @param device DDF instance of the device to use
     187 * @return Error code
     188 *
     189 * This function does all the preparatory work for hc and rh drivers:
     190 *  - gets device's hw resources
     191 *  - attempts to enable interrupts
     192 *  - registers interrupt handler
     193 *  - calls driver specific initialization
     194 *  - registers root hub
     195 */
     196int hc_dev_add(ddf_dev_t *device)
     197{
     198        int ret = EOK;
     199        assert(device);
     200
     201        if (!hc_driver->hc_add) {
     202                usb_log_error("Driver '%s' does not support adding devices.", hc_driver->name);
     203                return ENOTSUP;
     204        }
     205
     206        ret = hcd_ddf_setup_hc(device, hc_driver->hc_device_size);
     207        if (ret != EOK) {
     208                usb_log_error("Failed to setup HC device.\n");
     209                return ret;
     210        }
     211
     212        hc_device_t *hcd = dev_to_hcd(device);
     213
     214        hw_res_list_parsed_t hw_res;
     215        ret = hcd_ddf_get_registers(hcd, &hw_res);
     216        if (ret != EOK) {
     217                usb_log_error("Failed to get register memory addresses "
     218                    "for `%s': %s.\n", ddf_dev_get_name(device),
     219                    str_error(ret));
     220                goto err_hcd;
     221        }
     222
     223        ret = hc_driver->hc_add(hcd, &hw_res);
     224        if (ret != EOK) {
     225                usb_log_error("Failed to init HCD.\n");
     226                goto err_hw_res;
     227        }
     228
     229        assert(hcd->bus);
     230
     231        /* Setup interrupts  */
     232        hcd->irq_cap = hcd_ddf_setup_interrupts(hcd, &hw_res);
     233        if (hcd->irq_cap >= 0) {
     234                usb_log_debug("Hw interrupts enabled.\n");
     235        }
     236
     237        /* Claim the device from BIOS */
     238        if (hc_driver->claim)
     239                ret = hc_driver->claim(hcd);
     240        if (ret != EOK) {
     241                usb_log_error("Failed to claim `%s' for `%s': %s",
     242                    ddf_dev_get_name(device), hc_driver->name, str_error(ret));
     243                goto err_irq;
     244        }
     245
     246        /* Start hw */
     247        if (hc_driver->start)
     248                ret = hc_driver->start(hcd);
     249        if (ret != EOK) {
     250                usb_log_error("Failed to start HCD: %s.\n", str_error(ret));
     251                goto err_irq;
     252        }
     253
     254        const bus_ops_t *ops = BUS_OPS_LOOKUP(hcd->bus->ops, status);
     255
     256        /* Need working irq replacement to setup root hub */
     257        if (hcd->irq_cap < 0 && ops) {
     258                hcd->polling_fibril = fibril_create(interrupt_polling, hcd->bus);
     259                if (!hcd->polling_fibril) {
     260                        usb_log_error("Failed to create polling fibril\n");
     261                        ret = ENOMEM;
     262                        goto err_started;
     263                }
     264                fibril_add_ready(hcd->polling_fibril);
     265                usb_log_warning("Failed to enable interrupts: %s."
     266                    " Falling back to polling.\n", str_error(hcd->irq_cap));
     267        }
     268
     269        /*
     270         * Creating root hub registers a new USB device so HC
     271         * needs to be ready at this time.
     272         */
     273        if (hc_driver->setup_root_hub)
     274                ret = hc_driver->setup_root_hub(hcd);
     275        if (ret != EOK) {
     276                usb_log_error("Failed to setup HC root hub: %s.\n",
     277                    str_error(ret));
     278                goto err_polling;
     279        }
     280
     281        usb_log_info("Controlling new `%s' device `%s'.\n",
     282           hc_driver->name, ddf_dev_get_name(device));
     283        return EOK;
     284
     285err_polling:
     286        // TODO: Stop the polling fibril (refactor the interrupt_polling func)
     287        //
     288err_started:
     289        if (hc_driver->stop)
     290                hc_driver->stop(hcd);
     291err_irq:
     292        unregister_interrupt_handler(device, hcd->irq_cap);
     293        if (hc_driver->hc_remove)
     294                hc_driver->hc_remove(hcd);
     295err_hw_res:
     296        hw_res_list_parsed_clean(&hw_res);
     297err_hcd:
     298        hcd_ddf_clean_hc(hcd);
     299        return ret;
     300}
     301
     302int hc_dev_remove(ddf_dev_t *dev)
     303{
     304        int err;
     305        hc_device_t *hcd = dev_to_hcd(dev);
     306
     307        if (hc_driver->stop)
     308                if ((err = hc_driver->stop(hcd)))
     309                        return err;
     310
     311        unregister_interrupt_handler(dev, hcd->irq_cap);
     312
     313        if (hc_driver->hc_remove)
     314                if ((err = hc_driver->hc_remove(hcd)))
     315                        return err;
     316
     317        hcd_ddf_clean_hc(hcd);
     318
     319        // TODO probably not complete
     320
     321        return EOK;
     322}
     323
     324int hc_dev_gone(ddf_dev_t *dev)
     325{
     326        int err = ENOTSUP;
     327        hc_device_t *hcd = dev_to_hcd(dev);
     328
     329        if (hc_driver->hc_gone)
     330                err = hc_driver->hc_gone(hcd);
     331
     332        hcd_ddf_clean_hc(hcd);
     333
     334        return err;
     335}
     336
     337int hc_fun_online(ddf_fun_t *fun)
     338{
     339        assert(fun);
     340
     341        device_t *dev = ddf_fun_data_get(fun);
     342        assert(dev);
     343
     344        usb_log_info("Device(%d): Requested to be brought online.", dev->address);
     345        return bus_device_online(dev);
     346}
     347
     348int hc_fun_offline(ddf_fun_t *fun)
     349{
     350        assert(fun);
     351
     352        device_t *dev = ddf_fun_data_get(fun);
     353        assert(dev);
     354
     355        usb_log_info("Device(%d): Requested to be taken offline.", dev->address);
     356        return bus_device_offline(dev);
    65357}
    66358
     
    72364 * @return Max packet size for EP 0
    73365 */
    74 int hcd_get_ep0_max_packet_size(uint16_t *mps, hcd_t *hcd, device_t *dev)
     366int hcd_get_ep0_max_packet_size(uint16_t *mps, bus_t *bus, device_t *dev)
    75367{
    76368        assert(mps);
     
    97389
    98390        usb_log_debug("Requesting first 8B of device descriptor to determine MPS.");
    99         ssize_t got = hcd_send_batch_sync(hcd, dev, control_ep, USB_DIRECTION_IN,
     391        ssize_t got = bus_device_send_batch_sync(dev, control_ep, USB_DIRECTION_IN,
    100392            (char *) &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8,
    101393            "read first 8 bytes of dev descriptor");
     
    156448 *
    157449 */
    158 static toggle_reset_mode_t hcd_get_request_toggle_reset_mode(
     450toggle_reset_mode_t hcd_get_request_toggle_reset_mode(
    159451    const usb_device_request_setup_packet_t *request)
    160452{
     
    186478}
    187479
    188 /** Prepare generic usb_transfer_batch and schedule it.
    189  * @param hcd Host controller driver.
    190  * @param target address and endpoint number.
    191  * @param setup_data Data to use in setup stage (Control communication type)
    192  * @param in Callback for device to host communication.
    193  * @param out Callback for host to device communication.
    194  * @param arg Callback parameter.
    195  * @param name Communication identifier (for nicer output).
    196  * @return Error code.
    197  */
    198 int hcd_send_batch(hcd_t *hcd, device_t *device, usb_target_t target,
    199     usb_direction_t direction, char *data, size_t size, uint64_t setup_data,
    200     usbhc_iface_transfer_callback_t on_complete, void *arg, const char *name)
    201 {
    202         assert(hcd);
    203         assert(device->address == target.address);
    204 
    205         if (!hcd->ops.schedule) {
    206                 usb_log_error("HCD does not implement scheduler.\n");
    207                 return ENOTSUP;
    208         }
    209 
    210         endpoint_t *ep = bus_find_endpoint(device, target, direction);
    211         if (ep == NULL) {
    212                 usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
    213                     device->address, target.endpoint, name);
    214                 return ENOENT;
    215         }
    216 
    217         // TODO cut here aka provide helper to call with instance of endpoint_t in hand
    218         assert(ep->device == device);
    219 
    220         usb_log_debug2("%s %d:%d %zu(%zu).\n",
    221             name, target.address, target.endpoint, size, ep->max_packet_size);
    222 
    223         const size_t bw = endpoint_count_bw(ep, size);
    224         /* Check if we have enough bandwidth reserved */
    225         if (ep->bandwidth < bw) {
    226                 usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
    227                     "but only %zu is reserved.\n",
    228                     device->address, ep->endpoint, name, bw, ep->bandwidth);
    229                 return ENOSPC;
    230         }
    231 
    232         usb_transfer_batch_t *batch = usb_transfer_batch_create(ep);
    233         if (!batch) {
    234                 usb_log_error("Failed to create transfer batch.\n");
    235                 return ENOMEM;
    236         }
    237 
    238         batch->target = target;
    239         batch->buffer = data;
    240         batch->buffer_size = size;
    241         batch->setup.packed = setup_data;
    242         batch->dir = direction;
    243         batch->on_complete = on_complete;
    244         batch->on_complete_data = arg;
    245 
    246         /* Check for commands that reset toggle bit */
    247         if (ep->transfer_type == USB_TRANSFER_CONTROL)
    248                 batch->toggle_reset_mode
    249                         = hcd_get_request_toggle_reset_mode(&batch->setup.packet);
    250 
    251         const int ret = hcd->ops.schedule(hcd, batch);
    252         if (ret != EOK) {
    253                 usb_log_warning("Batch %p failed to schedule: %s", batch, str_error(ret));
    254                 usb_transfer_batch_destroy(batch);
    255         }
    256 
    257         /* Drop our own reference to ep. */
    258         endpoint_del_ref(ep);
    259 
    260         return ret;
    261 }
    262 
    263 typedef struct {
    264         fibril_mutex_t done_mtx;
    265         fibril_condvar_t done_cv;
    266         unsigned done;
    267 
    268         size_t transfered_size;
    269         int error;
    270 } sync_data_t;
    271 
    272 static int sync_transfer_complete(void *arg, int error, size_t transfered_size)
    273 {
    274         sync_data_t *d = arg;
    275         assert(d);
    276         d->transfered_size = transfered_size;
    277         d->error = error;
    278         fibril_mutex_lock(&d->done_mtx);
    279         d->done = 1;
    280         fibril_condvar_broadcast(&d->done_cv);
    281         fibril_mutex_unlock(&d->done_mtx);
    282         return EOK;
    283 }
    284 
    285 ssize_t hcd_send_batch_sync(hcd_t *hcd, device_t *device, usb_target_t target,
    286     usb_direction_t direction, char *data, size_t size, uint64_t setup_data,
    287     const char *name)
    288 {
    289         assert(hcd);
    290         sync_data_t sd = { .done = 0 };
    291         fibril_mutex_initialize(&sd.done_mtx);
    292         fibril_condvar_initialize(&sd.done_cv);
    293 
    294         const int ret = hcd_send_batch(hcd, device, target, direction,
    295             data, size, setup_data,
    296             sync_transfer_complete, &sd, name);
    297         if (ret != EOK)
    298                 return ret;
    299 
    300         fibril_mutex_lock(&sd.done_mtx);
    301         while (!sd.done)
    302                 fibril_condvar_wait(&sd.done_cv, &sd.done_mtx);
    303         fibril_mutex_unlock(&sd.done_mtx);
    304 
    305         return (sd.error == EOK)
    306                 ? (ssize_t) sd.transfered_size
    307                 : (ssize_t) sd.error;
    308 }
    309 
    310480
    311481/**
  • uspace/lib/usbhost/src/usb2_bus.c

    r1ea0bbf r32fb6bce  
    205205
    206206        usb2_bus_t *bus = (usb2_bus_t *) dev->bus;
    207         hcd_t *hcd = (hcd_t *) bus->base.hcd;
    208207
    209208        /* The default address is currently reserved for this device */
     
    231230
    232231        uint16_t max_packet_size;
    233         if ((err = hcd_get_ep0_max_packet_size(&max_packet_size, hcd, dev)))
     232        if ((err = hcd_get_ep0_max_packet_size(&max_packet_size, &bus->base, dev)))
    234233                goto err_address;
    235234
     
    238237
    239238        usb_log_debug("Device(%d): Setting USB address.", address);
    240         err = hcd_send_batch_sync(hcd, dev, usb2_default_target, USB_DIRECTION_OUT,
     239        err = bus_device_send_batch_sync(dev, usb2_default_target, USB_DIRECTION_OUT,
    241240            NULL, 0, *(uint64_t *)&set_address, "set address");
    242241        if (err != 0) {
     
    315314
    316315        /* Read the device descriptor, derive the match ids */
    317         if ((err = hcd_ddf_device_explore(dev))) {
     316        if ((err = hcd_device_explore(dev))) {
    318317                usb_log_error("Device(%d): Failed to explore device: %s", dev->address, str_error(err));
    319318                release_address(bus, dev->address);
     
    463462 * @return Error code.
    464463 */
    465 int usb2_bus_init(usb2_bus_t *bus, hcd_t *hcd, size_t available_bandwidth)
     464int usb2_bus_init(usb2_bus_t *bus, size_t available_bandwidth)
    466465{
    467466        assert(bus);
    468467
    469         bus_init(&bus->base, hcd, sizeof(device_t));
     468        bus_init(&bus->base, sizeof(device_t));
    470469        bus->base.ops = &usb2_bus_ops;
    471470
Note: See TracChangeset for help on using the changeset viewer.