Changeset 32fb6bce in mainline for uspace/drv/bus/usb/ohci


Ignore:
Timestamp:
2017-12-18T22:50:21Z (8 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/drv/bus/usb/ohci
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.