Changeset e4d7363 in mainline


Ignore:
Timestamp:
2017-06-22T21:34:39Z (7 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
91ca111
Parents:
cb89430
Message:

usbhost: refactor the initialization

Before that, drivers had to setup MMIO range multiple times, or even parse hw
resources themselves again. The former init method was split in half - init and
start. Init shall allocate and initialize inner structures, start shall start
the HC.

In the XHCI it is demonstrated how to isolate inner HC implementation from the
fact this driver is using libusbhost. It adds some boilerplate code, but
I think it leads to cleaner design.

Location:
uspace
Files:
16 edited

Legend:

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

    rcb89430 re4d7363  
    8989};
    9090
    91 static void hc_start(hc_t *instance);
    9291static int hc_init_memory(hc_t *instance);
    9392
     
    9897 * @return Error code.
    9998 */
    100 int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)
     99int ehci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
    101100{
    102101        assert(code);
    103102        assert(hw_res);
     103
     104        hc_t *instance = hcd_get_driver_data(hcd);
    104105
    105106        if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1)
     
    128129
    129130        memcpy(code->cmds, ehci_irq_commands, sizeof(ehci_irq_commands));
    130         ehci_caps_regs_t *caps = NULL;
    131 
    132         int ret = pio_enable_range(&regs, (void**)&caps);
    133         if (ret != EOK) {
    134                 free(code->ranges);
    135                 free(code->cmds);
    136                 return ret;
    137         }
    138 
    139         ehci_regs_t *registers =
    140             (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(caps->caplength));
    141         code->cmds[0].addr = (void *) &registers->usbsts;
    142         code->cmds[3].addr = (void *) &registers->usbsts;
     131
     132        code->cmds[0].addr = (void *) &instance->registers->usbsts;
     133        code->cmds[3].addr = (void *) &instance->registers->usbsts;
    143134        EHCI_WR(code->cmds[1].value, EHCI_USED_INTERRUPTS);
    144135
     
    156147 * @return Error code
    157148 */
    158 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
     149int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res)
    159150{
    160151        assert(instance);
     
    172163                return ret;
    173164        }
     165
    174166        usb_log_info("HC(%p): Device registers at %"PRIx64" (%zuB) accessible.",
    175167            instance, hw_res->mem_ranges.ranges[0].address.absolute,
     
    195187        ehci_rh_init(
    196188            &instance->rh, instance->caps, instance->registers, "ehci rh");
    197         usb_log_debug("HC(%p): Starting HW.", instance);
    198         hc_start(instance);
    199189
    200190        return EOK;
     
    368358 * @param[in] instance EHCI hc driver structure.
    369359 */
    370 void hc_start(hc_t *instance)
    371 {
    372         assert(instance);
     360int hc_start(hc_t *instance, bool interrupts)
     361{
     362        assert(instance);
     363        usb_log_debug("HC(%p): Starting HW.", instance);
     364
    373365        /* Turn off the HC if it's running, Reseting a running device is
    374366         * undefined */
     
    435427        EHCI_WR(instance->registers->usbsts, EHCI_RD(instance->registers->usbsts));
    436428        EHCI_WR(instance->registers->usbintr, EHCI_USED_INTERRUPTS);
     429
     430        return EOK;
    437431}
    438432
  • uspace/drv/bus/usb/ehci/hc.h

    rcb89430 re4d7363  
    8282} hc_t;
    8383
    84 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts);
     84int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res);
     85int hc_start(hc_t *instance, bool interrupts);
    8586void hc_fini(hc_t *instance);
    8687
     
    8889void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep);
    8990
    90 int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res);
     91int ehci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res);
    9192
    9293void ehci_hc_interrupt(hcd_t *hcd, uint32_t status);
  • uspace/drv/bus/usb/ehci/main.c

    rcb89430 re4d7363  
    5252#define NAME "ehci"
    5353
    54 static int ehci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool);
     54static int ehci_driver_init(hcd_t *, const hw_res_list_parsed_t *);
     55static int ehci_driver_claim(hcd_t *, ddf_dev_t *);
     56static int ehci_driver_start(hcd_t *, bool);
    5557static void ehci_driver_fini(hcd_t *);
    5658
    5759static const ddf_hc_driver_t ehci_hc_driver = {
    58         .claim = disable_legacy,
    5960        .hc_speed = USB_SPEED_HIGH,
     61        .name = "EHCI-PCI",
     62        .init = ehci_driver_init,
    6063        .irq_code_gen = ehci_hc_gen_irq_code,
    61         .init = ehci_driver_init,
     64        .claim = ehci_driver_claim,
     65        .start = ehci_driver_start,
    6266        .fini = ehci_driver_fini,
    63         .name = "EHCI-PCI",
    6467        .ops = {
    6568                .schedule       = ehci_hc_schedule,
     
    7275
    7376
    74 static int ehci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res,
    75     bool irq)
     77static int ehci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res)
    7678{
    7779        assert(hcd);
     
    8284                return ENOMEM;
    8385
    84         const int ret = hc_init(instance, res, irq);
     86        const int ret = hc_init(instance, res);
    8587        if (ret == EOK) {
    8688                hcd_set_implementation(hcd, instance, &ehci_hc_driver.ops);
     
    8991        }
    9092        return ret;
     93}
     94
     95static int ehci_driver_claim(hcd_t *hcd, ddf_dev_t *dev)
     96{
     97        hc_t *instance = hcd_get_driver_data(hcd);
     98        assert(instance);
     99
     100        return disable_legacy(instance, dev);
     101}
     102
     103static int ehci_driver_start(hcd_t *hcd, bool irq) {
     104        hc_t *instance = hcd_get_driver_data(hcd);
     105        assert(instance);
     106
     107        return hc_start(instance, irq);
    91108}
    92109
  • uspace/drv/bus/usb/ehci/res.c

    rcb89430 re4d7363  
    172172}
    173173
    174 int disable_legacy(ddf_dev_t *device)
     174int disable_legacy(hc_t *hc, ddf_dev_t *device)
    175175{
    176176        assert(device);
     
    183183        usb_log_debug("Disabling EHCI legacy support.\n");
    184184
    185         hw_res_list_parsed_t res;
    186         hw_res_list_parsed_init(&res);
    187         int ret = hw_res_get_list_parsed(parent_sess, &res, 0);
    188         if (ret != EOK) {
    189                 usb_log_error("Failed to get resource list: %s\n",
    190                     str_error(ret));
    191                 goto clean;
    192         }
    193 
    194         if (res.mem_ranges.count < 1) {
    195                 usb_log_error("Incorrect mem range count: %zu",
    196                     res.mem_ranges.count);
    197                 ret = EINVAL;
    198                 goto clean;
    199         }
    200 
    201         /* Map EHCI registers */
    202         void *regs = NULL;
    203         ret = pio_enable_range(&res.mem_ranges.ranges[0], &regs);
    204         if (ret != EOK) {
    205                 usb_log_error("Failed to map registers %p: %s.\n",
    206                     RNGABSPTR(res.mem_ranges.ranges[0]), str_error(ret));
    207                 goto clean;
    208         }
    209 
    210         usb_log_debug("Registers mapped at: %p.\n", regs);
    211 
    212         ehci_caps_regs_t *ehci_caps = regs;
    213 
    214         const uint32_t hcc_params = EHCI_RD(ehci_caps->hccparams);
     185
     186        const uint32_t hcc_params = EHCI_RD(hc->caps->hccparams);
    215187        usb_log_debug2("Value of hcc params register: %x.\n", hcc_params);
    216188
     
    221193        usb_log_debug2("Value of EECP: %x.\n", eecp);
    222194
    223         ret = disable_extended_caps(parent_sess, eecp);
     195        int ret = disable_extended_caps(parent_sess, eecp);
    224196        if (ret != EOK) {
    225197                usb_log_error("Failed to disable extended capabilities: %s.\n",
     
    228200        }
    229201clean:
    230         //TODO unmap registers
    231         hw_res_list_parsed_clean(&res);
    232202        async_hangup(parent_sess);
    233203        return ret;
  • uspace/drv/bus/usb/ehci/res.h

    rcb89430 re4d7363  
    3939#include <device/hw_res_parsed.h>
    4040
    41 extern int disable_legacy(ddf_dev_t *);
     41#include "hc.h"
     42
     43extern int disable_legacy(hc_t *, ddf_dev_t *);
    4244
    4345#endif
  • uspace/drv/bus/usb/ohci/hc.c

    rcb89430 re4d7363  
    8989};
    9090
    91 static void hc_gain_control(hc_t *instance);
    92 static void hc_start(hc_t *instance);
    9391static int hc_init_transfer_lists(hc_t *instance);
    9492static int hc_init_memory(hc_t *instance);
     
    103101 * @return Error code.
    104102 */
    105 int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)
     103int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
    106104{
    107105        assert(code);
     
    151149 * @return Error code
    152150 */
    153 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
     151int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res)
    154152{
    155153        assert(instance);
     
    172170        list_initialize(&instance->pending_batches);
    173171        fibril_mutex_initialize(&instance->guard);
    174         instance->hw_interrupts = interrupts;
    175172
    176173        ret = hc_init_memory(instance);
     
    181178                return ret;
    182179        }
    183 
    184         hc_gain_control(instance);
    185 
    186         ohci_rh_init(&instance->rh, instance->registers, "ohci rh");
    187         hc_start(instance);
    188180
    189181        return EOK;
     
    443435void hc_start(hc_t *instance)
    444436{
     437        ohci_rh_init(&instance->rh, instance->registers, "ohci rh");
     438
    445439        /* OHCI guide page 42 */
    446440        assert(instance);
  • uspace/drv/bus/usb/ohci/hc.h

    rcb89430 re4d7363  
    8080} hc_t;
    8181
    82 extern int hc_init(hc_t *, const hw_res_list_parsed_t *, bool);
     82extern int hc_init(hc_t *, const hw_res_list_parsed_t *);
     83extern void hc_gain_control(hc_t *instance);
     84extern void hc_start(hc_t *instance);
    8385extern void hc_fini(hc_t *);
    8486
     
    8688extern void hc_dequeue_endpoint(hc_t *, const endpoint_t *);
    8789
    88 int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res);
     90int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res);
    8991
    9092extern void ohci_hc_interrupt(hcd_t *, uint32_t);
  • uspace/drv/bus/usb/ohci/main.c

    rcb89430 re4d7363  
    4747
    4848#define NAME "ohci"
    49 static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool);
     49static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *);
     50static int ohci_driver_start(hcd_t *, bool);
     51static int ohci_driver_claim(hcd_t *, ddf_dev_t *);
    5052static void ohci_driver_fini(hcd_t *);
    5153
     
    5456        .irq_code_gen = ohci_hc_gen_irq_code,
    5557        .init = ohci_driver_init,
     58        .claim = ohci_driver_claim,
     59        .start = ohci_driver_start,
    5660        .fini = ohci_driver_fini,
    5761        .name = "OHCI",
     
    6670
    6771
    68 static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq)
     72static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res)
    6973{
    7074        assert(hcd);
     
    7579                return ENOMEM;
    7680
    77         const int ret = hc_init(instance, res, irq);
     81        const int ret = hc_init(instance, res);
    7882        if (ret == EOK) {
    7983                hcd_set_implementation(hcd, instance, &ohci_hc_driver.ops);
     
    8286        }
    8387        return ret;
     88}
     89
     90static int ohci_driver_claim(hcd_t *hcd, ddf_dev_t *dev)
     91{
     92        hc_t *hc = hcd_get_driver_data(hcd);
     93        assert(hc);
     94
     95        hc_gain_control(hc);
     96
     97        return EOK;
     98}
     99
     100static int ohci_driver_start(hcd_t *hcd, bool interrupts)
     101{
     102        hc_t *hc = hcd_get_driver_data(hcd);
     103        assert(hc);
     104
     105        hc->hw_interrupts = interrupts;
     106        hc_start(hc);
     107        return EOK;
    84108}
    85109
  • uspace/drv/bus/usb/uhci/hc.c

    rcb89430 re4d7363  
    106106 * @return Error code.
    107107 */
    108 int uhci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)
     108int uhci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
    109109{
    110110        assert(code);
     
    214214 * interrupt fibrils.
    215215 */
    216 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
     216int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res)
    217217{
    218218        assert(instance);
     
    222222            return EINVAL;
    223223
    224         instance->hw_interrupts = interrupts;
    225224        instance->hw_failures = 0;
    226225
     
    246245        }
    247246
     247        return EOK;
     248}
     249
     250void hc_start(hc_t *instance)
     251{
    248252        hc_init_hw(instance);
    249253        (void)hc_debug_checker;
    250254
    251255        uhci_rh_init(&instance->rh, instance->registers->ports, "uhci");
    252 
    253         return EOK;
    254256}
    255257
  • uspace/drv/bus/usb/uhci/hc.h

    rcb89430 re4d7363  
    124124} hc_t;
    125125
    126 extern int hc_init(hc_t *, const hw_res_list_parsed_t *, bool);
     126extern int hc_init(hc_t *, const hw_res_list_parsed_t *);
     127extern void hc_start(hc_t *);
    127128extern void hc_fini(hc_t *);
    128129
    129 extern int uhci_hc_gen_irq_code(irq_code_t *, const hw_res_list_parsed_t *);
     130extern int uhci_hc_gen_irq_code(irq_code_t *, hcd_t *,const hw_res_list_parsed_t *);
    130131
    131132extern void uhci_hc_interrupt(hcd_t *, uint32_t);
  • uspace/drv/bus/usb/uhci/main.c

    rcb89430 re4d7363  
    5050#define NAME "uhci"
    5151
    52 static int uhci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool);
     52static int uhci_driver_init(hcd_t *, const hw_res_list_parsed_t *);
     53static int uhci_driver_start(hcd_t *, bool);
    5354static void uhci_driver_fini(hcd_t *);
    54 static int disable_legacy(ddf_dev_t *);
     55static int disable_legacy(hcd_t *, ddf_dev_t *);
    5556
    5657static const ddf_hc_driver_t uhci_hc_driver = {
     
    5960        .irq_code_gen = uhci_hc_gen_irq_code,
    6061        .init = uhci_driver_init,
     62        .start = uhci_driver_start,
    6163        .fini = uhci_driver_fini,
    6264        .name = "UHCI",
     
    6870};
    6971
    70 static int uhci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq)
     72static int uhci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res)
    7173{
    7274        assert(hcd);
     
    7779                return ENOMEM;
    7880
    79         const int ret = hc_init(instance, res, irq);
     81        const int ret = hc_init(instance, res);
    8082        if (ret == EOK) {
    8183                hcd_set_implementation(hcd, instance, &uhci_hc_driver.ops);
     
    8486        }
    8587        return ret;
     88}
     89
     90static int uhci_driver_start(hcd_t *hcd, bool interrupts)
     91{
     92        assert(hcd);
     93        hc_t *hc = hcd_get_driver_data(hcd);
     94
     95        hc->hw_interrupts = interrupts;
     96        hc_start(hc);
     97        return EOK;
    8698}
    8799
     
    102114 * @return Error code.
    103115 */
    104 static int disable_legacy(ddf_dev_t *device)
     116static int disable_legacy(hcd_t *hcd, ddf_dev_t *device)
    105117{
    106118        assert(device);
  • uspace/drv/bus/usb/xhci/hc.c

    rcb89430 re4d7363  
    3737#include <str_error.h>
    3838#include <usb/debug.h>
    39 #include <usb/host/ddf_helpers.h>
    4039#include <usb/host/utils/malloc32.h>
    4140#include "debug.h"
     
    7069};
    7170
     71int hc_init_mmio(xhci_hc_t *hc, const hw_res_list_parsed_t *hw_res)
     72{
     73        int err;
     74
     75        if (hw_res->mem_ranges.count != 1) {
     76                usb_log_error("Unexpected MMIO area, bailing out.");
     77                return EINVAL;
     78        }
     79
     80        hc->mmio_range = hw_res->mem_ranges.ranges[0];
     81
     82        usb_log_debug("MMIO area at %p (size %zu), IRQ %d.\n",
     83            RNGABSPTR(hc->mmio_range), RNGSZ(hc->mmio_range), hw_res->irqs.irqs[0]);
     84
     85        if (RNGSZ(hc->mmio_range) < sizeof(xhci_cap_regs_t))
     86                return EOVERFLOW;
     87
     88        void *base;
     89        if ((err = pio_enable_range(&hc->mmio_range, &base)))
     90                return err;
     91
     92        hc->cap_regs = (xhci_cap_regs_t *)  base;
     93        hc->op_regs  = (xhci_op_regs_t *)  (base + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_LENGTH));
     94        hc->rt_regs  = (xhci_rt_regs_t *)  (base + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_RTSOFF));
     95        hc->db_arry  = (xhci_doorbell_t *) (base + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_DBOFF));
     96
     97        usb_log_debug2("Initialized MMIO reg areas:");
     98        usb_log_debug2("\tCapability regs: %p", hc->cap_regs);
     99        usb_log_debug2("\tOperational regs: %p", hc->op_regs);
     100        usb_log_debug2("\tRuntime regs: %p", hc->rt_regs);
     101        usb_log_debug2("\tDoorbell array base: %p", hc->db_arry);
     102
     103        xhci_dump_cap_regs(hc->cap_regs);
     104
     105        hc->ac64 = XHCI_REG_RD(hc->cap_regs, XHCI_CAP_AC64);
     106        hc->max_slots = XHCI_REG_RD(hc->cap_regs, XHCI_CAP_MAX_SLOTS);
     107
     108        return EOK;
     109}
     110
     111int hc_init_memory(xhci_hc_t *hc)
     112{
     113        int err;
     114
     115        hc->dcbaa = malloc32((1 + hc->max_slots) * sizeof(xhci_device_ctx_t));
     116        if (!hc->dcbaa)
     117                return ENOMEM;
     118
     119        if ((err = xhci_trb_ring_init(&hc->command_ring, hc)))
     120                goto err_dcbaa;
     121
     122        if ((err = xhci_event_ring_init(&hc->event_ring, hc)))
     123                goto err_cmd_ring;
     124
     125        // TODO: Allocate scratchpad buffers
     126
     127        return EOK;
     128
     129        xhci_event_ring_fini(&hc->event_ring);
     130err_cmd_ring:
     131        xhci_trb_ring_fini(&hc->command_ring);
     132err_dcbaa:
     133        free32(hc->dcbaa);
     134        return err;
     135}
     136
     137
    72138/**
    73139 * Generates code to accept interrupts. The xHCI is designed primarily for
     
    75141 * (except 0) are disabled.
    76142 */
    77 static int hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res)
    78 {
    79         int err;
    80 
     143int hc_irq_code_gen(irq_code_t *code, xhci_hc_t *hc, const hw_res_list_parsed_t *hw_res)
     144{
    81145        assert(code);
    82146        assert(hw_res);
    83147
    84         if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1) {
     148        if (hw_res->irqs.count != 1) {
    85149                usb_log_info("Unexpected HW resources to enable interrupts.");
    86150                return EINVAL;
     
    88152
    89153        addr_range_t mmio_range = hw_res->mem_ranges.ranges[0];
    90 
    91         if (RNGSZ(mmio_range) < sizeof(xhci_cap_regs_t))
    92                 return EOVERFLOW;
    93 
    94 
    95         xhci_cap_regs_t *cap_regs = NULL;
    96         if ((err = pio_enable_range(&mmio_range, (void **)&cap_regs)))
    97                 return EIO;
    98154
    99155        code->ranges = malloc(sizeof(irq_pio_range_t));
     
    116172        memcpy(code->cmds, irq_commands, sizeof(irq_commands));
    117173
    118         void *intr0_iman = RNGABSPTR(mmio_range) + XHCI_REG_RD(cap_regs, XHCI_CAP_RTSOFF) + offsetof(xhci_rt_regs_t, ir[0]);
     174        void *intr0_iman = RNGABSPTR(mmio_range) + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_RTSOFF) + offsetof(xhci_rt_regs_t, ir[0]);
    119175        code->cmds[0].addr = intr0_iman;
    120176        code->cmds[3].addr = intr0_iman;
     
    124180}
    125181
    126 static int hc_claim(ddf_dev_t *dev)
    127 {
    128         // TODO: implement handoff: section 4.22.1
     182int hc_claim(xhci_hc_t *hc, ddf_dev_t *dev)
     183{
     184        // TODO: impl
    129185        return EOK;
    130186}
     
    152208 * Initialize the HC: section 4.2
    153209 */
    154 static int hc_start(xhci_hc_t *hc, bool irq)
     210int hc_start(xhci_hc_t *hc, bool irq)
    155211{
    156212        int err;
     
    191247}
    192248
    193 static int hc_init(hcd_t *hcd, const hw_res_list_parsed_t *hw_res, bool irq)
    194 {
    195         int err;
    196 
    197         assert(hcd);
    198         assert(hw_res);
    199         assert(hcd_get_driver_data(hcd) == NULL);
    200 
    201         /* Initialize the MMIO ranges */
    202         if (hw_res->mem_ranges.count != 1) {
    203                 usb_log_error("Unexpected MMIO area, bailing out.");
    204                 return EINVAL;
    205         }
    206 
    207         addr_range_t mmio_range = hw_res->mem_ranges.ranges[0];
    208 
    209         usb_log_debug("MMIO area at %p (size %zu), IRQ %d.\n",
    210             RNGABSPTR(mmio_range), RNGSZ(mmio_range), hw_res->irqs.irqs[0]);
    211 
    212         if (RNGSZ(mmio_range) < sizeof(xhci_cap_regs_t))
    213                 return EOVERFLOW;
    214 
    215         void *base;
    216         if ((err = pio_enable_range(&mmio_range, &base)))
    217                 return err;
    218 
    219         xhci_hc_t *hc = malloc(sizeof(xhci_hc_t));
    220         if (!hc)
    221                 return ENOMEM;
    222 
    223         hc->cap_regs = (xhci_cap_regs_t *)  base;
    224         hc->op_regs  = (xhci_op_regs_t *)  (base + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_LENGTH));
    225         hc->rt_regs  = (xhci_rt_regs_t *)  (base + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_RTSOFF));
    226         hc->db_arry  = (xhci_doorbell_t *) (base + XHCI_REG_RD(hc->cap_regs, XHCI_CAP_DBOFF));
    227 
    228         usb_log_debug2("Initialized MMIO reg areas:");
    229         usb_log_debug2("\tCapability regs: %p", hc->cap_regs);
    230         usb_log_debug2("\tOperational regs: %p", hc->op_regs);
    231         usb_log_debug2("\tRuntime regs: %p", hc->rt_regs);
    232         usb_log_debug2("\tDoorbell array base: %p", hc->db_arry);
    233 
    234         xhci_dump_cap_regs(hc->cap_regs);
    235 
    236         hc->ac64 = XHCI_REG_RD(hc->cap_regs, XHCI_CAP_AC64);
    237         hc->max_slots = XHCI_REG_RD(hc->cap_regs, XHCI_CAP_MAX_SLOTS);
    238 
    239         hc->dcbaa = malloc32((1 + hc->max_slots) * sizeof(xhci_device_ctx_t));
    240         if (!hc->dcbaa)
    241                 goto err_hc;
    242 
    243         if ((err = xhci_trb_ring_init(&hc->command_ring, hc)))
    244                 goto err_dcbaa;
    245 
    246         if ((err = xhci_event_ring_init(&hc->event_ring, hc)))
    247                 goto err_cmd_ring;
    248 
    249         // TODO: Allocate scratchpad buffers
    250 
    251         hcd_set_implementation(hcd, hc, &xhci_ddf_hc_driver.ops);
    252 
    253         if ((err = hc_start(hc, irq)))
    254                 goto err_event_ring;
    255 
    256         return EOK;
    257 
    258 err_event_ring:
    259         xhci_event_ring_fini(&hc->event_ring);
    260 err_cmd_ring:
    261         xhci_trb_ring_fini(&hc->command_ring);
    262 err_dcbaa:
    263         free32(hc->dcbaa);
    264 err_hc:
    265         free(hc);
    266         hcd_set_implementation(hcd, NULL, NULL);
    267         return err;
    268 }
    269 
    270 static int hc_status(hcd_t *hcd, uint32_t *status)
    271 {
    272         xhci_hc_t *hc = hcd_get_driver_data(hcd);
    273         assert(hc);
    274         assert(status);
    275 
    276         *status = 0;
    277         if (hc->op_regs) {
    278                 *status = XHCI_REG_RD(hc->op_regs, XHCI_OP_STATUS);
    279                 XHCI_REG_WR(hc->op_regs, XHCI_OP_STATUS, *status & XHCI_STATUS_ACK_MASK);
    280         }
     249int hc_status(xhci_hc_t *hc, uint32_t *status)
     250{
     251        *status = XHCI_REG_RD(hc->op_regs, XHCI_OP_STATUS);
     252        XHCI_REG_WR(hc->op_regs, XHCI_OP_STATUS, *status & XHCI_STATUS_ACK_MASK);
     253
    281254        usb_log_debug2("HC(%p): Read status: %x", hc, *status);
    282255        return EOK;
     
    305278}
    306279
    307 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    308 {
    309         xhci_hc_t *hc = hcd_get_driver_data(hcd);
    310         assert(hc);
    311 
     280int hc_schedule(xhci_hc_t *hc, usb_transfer_batch_t *batch)
     281{
    312282        xhci_dump_state(hc);
    313283        send_no_op_command(hc);
     
    346316}
    347317
    348 static void hc_interrupt(hcd_t *hcd, uint32_t status)
    349 {
    350         xhci_hc_t *hc = hcd_get_driver_data(hcd);
    351         assert(hc);
    352 
     318void hc_interrupt(xhci_hc_t *hc, uint32_t status)
     319{
    353320        if (status & XHCI_REG_MASK(XHCI_OP_HSE)) {
    354321                usb_log_error("Host controller error occured. Bad things gonna happen...");
     
    375342}
    376343
    377 static void hc_fini(hcd_t *hcd)
    378 {
    379         xhci_hc_t *hc = hcd_get_driver_data(hcd);
    380         assert(hc);
    381 
    382         usb_log_info("Finishing");
    383 
     344void hc_fini(xhci_hc_t *hc)
     345{
    384346        xhci_trb_ring_fini(&hc->command_ring);
    385347        xhci_event_ring_fini(&hc->event_ring);
    386 
    387         free(hc);
    388         hcd_set_implementation(hcd, NULL, NULL);
    389 }
    390 
    391 const ddf_hc_driver_t xhci_ddf_hc_driver = {
    392         .hc_speed = USB_SPEED_SUPER,
    393         .irq_code_gen = hc_gen_irq_code,
    394         .claim = hc_claim,
    395         .init = hc_init,
    396         .fini = hc_fini,
    397         .name = "XHCI-PCI",
    398         .ops = {
    399                 .schedule       = hc_schedule,
    400                 .irq_hook       = hc_interrupt,
    401                 .status_hook    = hc_status,
    402         }
    403 };
     348        usb_log_info("HC(%p): Finalized.", hc);
     349}
    404350
    405351
  • uspace/drv/bus/usb/xhci/hc.h

    rcb89430 re4d7363  
    3434 */
    3535
    36 #include <usb/host/ddf_helpers.h>
     36#include <usb/host/usb_transfer_batch.h>
    3737#include "hw_struct/regs.h"
    3838#include "hw_struct/context.h"
     
    4444        xhci_rt_regs_t *rt_regs;
    4545        xhci_doorbell_t *db_arry;
     46
     47        addr_range_t mmio_range;
    4648
    4749        xhci_trb_ring_t command_ring;
     
    5557} xhci_hc_t;
    5658
    57 extern const ddf_hc_driver_t xhci_ddf_hc_driver;
    58 
     59int hc_init_mmio(xhci_hc_t *, const hw_res_list_parsed_t *);
     60int hc_init_memory(xhci_hc_t *);
     61int hc_claim(xhci_hc_t *, ddf_dev_t *);
     62int hc_irq_code_gen(irq_code_t *, xhci_hc_t *, const hw_res_list_parsed_t *);
     63int hc_start(xhci_hc_t *, bool);
     64int hc_schedule(xhci_hc_t *hc, usb_transfer_batch_t *batch);
     65int hc_status(xhci_hc_t *, uint32_t *);
     66void hc_interrupt(xhci_hc_t *, uint32_t);
     67void hc_fini(xhci_hc_t *);
    5968
    6069/**
  • uspace/drv/bus/usb/xhci/main.c

    rcb89430 re4d7363  
    4545#define NAME "xhci"
    4646
     47static int hc_driver_init(hcd_t *, const hw_res_list_parsed_t *);
     48static int hcd_irq_code_gen(irq_code_t *, hcd_t *, const hw_res_list_parsed_t *);
     49static int hcd_claim(hcd_t *, ddf_dev_t *);
     50static int hcd_start(hcd_t *, bool);
     51static int hcd_status(hcd_t *, uint32_t *);
     52static void hcd_interrupt(hcd_t *, uint32_t);
     53static int hcd_schedule(hcd_t *, usb_transfer_batch_t *);
     54static void hc_driver_fini(hcd_t *);
     55
     56static const ddf_hc_driver_t xhci_ddf_hc_driver = {
     57        .hc_speed = USB_SPEED_SUPER,
     58        .name = "XHCI-PCI",
     59        .init = hc_driver_init,
     60        .irq_code_gen = hcd_irq_code_gen,
     61        .claim = hcd_claim,
     62        .start = hcd_start,
     63        .fini = hc_driver_fini,
     64        .ops = {
     65                .schedule       = hcd_schedule,
     66                .irq_hook       = hcd_interrupt,
     67                .status_hook    = hcd_status,
     68        }
     69};
     70
     71static int hc_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
     72{
     73        int err;
     74
     75        xhci_hc_t *hc = malloc(sizeof(xhci_hc_t));
     76        if (!hc)
     77                return ENOMEM;
     78
     79        if ((err = hc_init_mmio(hc, hw_res)))
     80                goto err;
     81
     82        if ((err = hc_init_memory(hc)))
     83                goto err;
     84
     85        hcd_set_implementation(hcd, hc, &xhci_ddf_hc_driver.ops);
     86
     87        return EOK;
     88err:
     89        free(hc);
     90        return err;
     91}
     92
     93static int hcd_irq_code_gen(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
     94{
     95        xhci_hc_t *hc = hcd_get_driver_data(hcd);
     96        assert(hc);
     97
     98        return hc_irq_code_gen(code, hc, hw_res);
     99}
     100
     101static int hcd_claim(hcd_t *hcd, ddf_dev_t *dev)
     102{
     103        xhci_hc_t *hc = hcd_get_driver_data(hcd);
     104        assert(hc);
     105
     106        return hc_claim(hc, dev);
     107}
     108
     109static int hcd_start(hcd_t *hcd, bool irq)
     110{
     111        xhci_hc_t *hc = hcd_get_driver_data(hcd);
     112        assert(hc);
     113
     114        return hc_start(hc, irq);
     115}
     116
     117static int hcd_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
     118{
     119        xhci_hc_t *hc = hcd_get_driver_data(hcd);
     120        assert(hc);
     121
     122        return hc_schedule(hc, batch);
     123}
     124
     125static int hcd_status(hcd_t *hcd, uint32_t *status)
     126{
     127        xhci_hc_t *hc = hcd_get_driver_data(hcd);
     128        assert(hc);
     129        assert(status);
     130
     131        return hc_status(hc, status);
     132}
     133
     134static void hcd_interrupt(hcd_t *hcd, uint32_t status)
     135{
     136        xhci_hc_t *hc = hcd_get_driver_data(hcd);
     137        assert(hc);
     138
     139        hc_interrupt(hc, status);
     140}
     141
     142static void hc_driver_fini(hcd_t *hcd)
     143{
     144        xhci_hc_t *hc = hcd_get_driver_data(hcd);
     145        assert(hc);
     146
     147        hc_fini(hc);
     148        free(hc);
     149}
     150
    47151/** Initializes a new ddf driver instance of XHCI hcd.
    48152 *
  • uspace/lib/usbhost/include/usb/host/ddf_helpers.h

    rcb89430 re4d7363  
    4545#include <device/hw_res_parsed.h>
    4646
    47 typedef int (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *, bool);
     47typedef int (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *);
     48typedef int (*irq_code_gen_t)(irq_code_t *, hcd_t *, const hw_res_list_parsed_t *);
     49typedef int (*claim_t)(hcd_t *, ddf_dev_t *);
     50typedef int (*driver_start_t)(hcd_t *, bool irq);
     51
     52typedef void (*driver_stop_t)(hcd_t *);
    4853typedef void (*driver_fini_t)(hcd_t *);
    49 typedef int (*claim_t)(ddf_dev_t *);
    50 typedef int (*irq_code_gen_t)(irq_code_t *, const hw_res_list_parsed_t *);
    5154
     55/**
     56 * All callbacks are optional.
     57 */
    5258typedef struct {
    5359        hcd_ops_t ops;
    54         claim_t claim;
    5560        usb_speed_t hc_speed;
    56         driver_init_t init;
    57         driver_fini_t fini;
    58         interrupt_handler_t *irq_handler;
    59         irq_code_gen_t irq_code_gen;
    6061        const char *name;
     62
     63        interrupt_handler_t *irq_handler;  /**< Handler of IRQ. Do have generic implementation. */
     64
     65        /* Initialization sequence: */
     66        driver_init_t init;                /**< Initialize internal structures, memory */
     67        claim_t claim;                     /**< Claim device from BIOS */
     68        irq_code_gen_t irq_code_gen;       /**< Generate IRQ handling code */
     69        driver_start_t start;              /**< Start the HC */
     70
     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) */
    6174} ddf_hc_driver_t;
    6275
     
    7588    const hw_res_list_parsed_t *hw_res,
    7689    interrupt_handler_t handler,
    77     int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *));
     90    irq_code_gen_t gen_irq_code);
    7891void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev);
    7992
  • uspace/lib/usbhost/src/ddf_helpers.c

    rcb89430 re4d7363  
    753753    const hw_res_list_parsed_t *hw_res,
    754754    interrupt_handler_t handler,
    755     int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *hw_res))
    756 {
    757 
     755    irq_code_gen_t gen_irq_code)
     756{
    758757        assert(device);
     758
     759        hcd_t *hcd = dev_to_hcd(device);
     760
    759761        if (!handler || !gen_irq_code)
    760762                return ENOTSUP;
     
    762764        irq_code_t irq_code = {0};
    763765
    764         const int irq = gen_irq_code(&irq_code, hw_res);
     766        const int irq = gen_irq_code(&irq_code, hcd, hw_res);
    765767        if (irq < 0) {
    766768                usb_log_error("Failed to generate IRQ code: %s.\n",
     
    878880        if (ret != EOK) {
    879881                usb_log_error("Failed to setup generic HCD.\n");
    880                 hw_res_list_parsed_clean(&hw_res);
    881                 return ret;
    882         }
    883 
     882                goto err_hw_res;
     883        }
     884
     885        hcd_t *hcd = dev_to_hcd(device);
     886
     887        if (driver->init)
     888                ret = driver->init(hcd, &hw_res);
     889        if (ret != EOK) {
     890                usb_log_error("Failed to init HCD.\n");
     891                goto err_hcd;
     892        }
     893
     894        /* Setup interrupts  */
    884895        interrupt_handler_t *irq_handler =
    885896            driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler;
    886         const int irq = hcd_ddf_setup_interrupts(device, &hw_res, irq_handler,
    887             driver->irq_code_gen);
     897        const int irq = hcd_ddf_setup_interrupts(device, &hw_res, irq_handler, driver->irq_code_gen);
    888898        if (!(irq < 0)) {
    889899                usb_log_debug("Hw interrupts enabled.\n");
    890900        }
    891901
     902        /* Claim the device from BIOS */
    892903        if (driver->claim)
    893                 ret = driver->claim(device);
    894         if (ret != EOK) {
    895                 usb_log_error("Failed to claim `%s' for driver `%s'",
    896                     ddf_dev_get_name(device), driver->name);
    897                 return ret;
    898         }
    899 
    900 
    901         /* Init hw driver */
    902         hcd_t *hcd = dev_to_hcd(device);
    903         ret = driver->init(hcd, &hw_res, !(irq < 0));
    904         hw_res_list_parsed_clean(&hw_res);
    905         if (ret != EOK) {
    906                 usb_log_error("Failed to init HCD: %s.\n", str_error(ret));
    907                 goto irq_unregister;
     904                ret = driver->claim(hcd, device);
     905        if (ret != EOK) {
     906                usb_log_error("Failed to claim `%s' for driver `%s': %s",
     907                    ddf_dev_get_name(device), driver->name, str_error(ret));
     908                goto err_irq;
     909        }
     910
     911        /* Start hw driver */
     912        if (driver->start)
     913                ret = driver->start(hcd, !(irq < 0));
     914        if (ret != EOK) {
     915                usb_log_error("Failed to start HCD: %s.\n", str_error(ret));
     916                goto err_irq;
    908917        }
    909918
     
    914923                        usb_log_error("Failed to create polling fibril\n");
    915924                        ret = ENOMEM;
    916                         goto irq_unregister;
     925                        goto err_started;
    917926                }
    918927                fibril_add_ready(hcd->polling_fibril);
     
    929938                usb_log_error("Failed to setup HC root hub: %s.\n",
    930939                    str_error(ret));
    931                 driver->fini(dev_to_hcd(device));
    932 irq_unregister:
    933                 /* Unregistering non-existent should be ok */
    934                 unregister_interrupt_handler(device, irq);
    935                 hcd_ddf_clean_hc(device);
    936                 return ret;
     940                goto err_polling;
    937941        }
    938942
     
    940944            driver->name, ddf_dev_get_name(device));
    941945        return EOK;
     946       
     947err_polling:
     948        // TODO: Stop the polling fibril (refactor the interrupt_polling func)
     949        //
     950err_started:
     951        if (driver->stop)
     952                driver->stop(hcd);
     953err_irq:
     954        unregister_interrupt_handler(device, irq);
     955        if (driver->fini)
     956                driver->fini(hcd);
     957err_hcd:
     958        hcd_ddf_clean_hc(device);
     959err_hw_res:
     960        hw_res_list_parsed_clean(&hw_res);
     961        return ret;
    942962}
    943963/**
Note: See TracChangeset for help on using the changeset viewer.