Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 0206d35 in mainline


Ignore:
Timestamp:
2017-10-25T00:03:57Z (3 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
master
Children:
c3d926f
Parents:
56db65d
Message:

Moving things around to improve isolation of responsibilities

Bus interface was simplified, xHCI implementation of address_device was spread into stack of rh → bus → hc and back.

Location:
uspace
Files:
10 edited

Legend:

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

    r56db65d r0206d35  
    4949#include "transfers.h"
    5050
    51 /** TODO: Still some copy-pasta left...
    52  */
     51
     52/* FIXME Are these really static? Older HCs fetch it from descriptor. */
     53/* FIXME Add USB3 options, if applicable. */
     54static const usb_endpoint_desc_t ep0_desc = {
     55        .endpoint_no = 0,
     56        .direction = USB_DIRECTION_BOTH,
     57        .transfer_type = USB_TRANSFER_CONTROL,
     58        .max_packet_size = CTRL_PIPE_MIN_PACKET_SIZE,
     59        .packets = 1,
     60};
     61
     62static int prepare_endpoint(xhci_endpoint_t *ep, const usb_endpoint_desc_t *desc)
     63{
     64        /* Extract information from endpoint_desc */
     65        ep->base.target = (usb_target_t) {{
     66                .address = ep->base.device->address,
     67                .endpoint = desc->endpoint_no,
     68        }};
     69        ep->base.direction = desc->direction;
     70        ep->base.transfer_type = desc->transfer_type;
     71        ep->base.max_packet_size = desc->max_packet_size;
     72        ep->base.packets = desc->packets;
     73        ep->max_streams = desc->usb3.max_streams;
     74        ep->max_burst = desc->usb3.max_burst;
     75        // TODO add this property to usb_endpoint_desc_t and fetch it from ss companion desc
     76        ep->mult = 0;
     77
     78        return xhci_endpoint_alloc_transfer_ds(ep);
     79}
     80
     81static endpoint_t *create_endpoint(bus_t *base);
     82
     83static int address_device(xhci_hc_t *hc, xhci_device_t *dev)
     84{
     85        int err;
     86
     87        /* Enable new slot. */
     88        if ((err = hc_enable_slot(hc, &dev->slot_id)) != EOK)
     89                return err;
     90        usb_log_debug2("Obtained slot ID: %u.\n", dev->slot_id);
     91
     92        /* Create and configure control endpoint. */
     93        endpoint_t *ep0_base = create_endpoint(&hc->bus.base);
     94        if (!ep0_base)
     95                goto err_slot;
     96
     97        /* Temporary reference */
     98        endpoint_add_ref(ep0_base);
     99
     100        ep0_base->device = &dev->base;
     101        xhci_endpoint_t *ep0 = xhci_endpoint_get(ep0_base);
     102
     103        if ((err = prepare_endpoint(ep0, &ep0_desc)))
     104                goto err_ep;
     105
     106        /* Address device */
     107        if ((err = hc_address_device(hc, dev, ep0)))
     108                goto err_prepared_ep;
     109
     110        /* Register EP0, passing Temporary reference */
     111        ep0->base.target.address = dev->base.address;
     112        dev->endpoints[0] = ep0;
     113
     114        return EOK;
     115
     116err_prepared_ep:
     117        xhci_endpoint_free_transfer_ds(ep0);
     118err_ep:
     119        endpoint_del_ref(ep0_base);
     120err_slot:
     121        hc_disable_slot(hc, dev->slot_id);
     122        return err;
     123}
     124
    53125int xhci_bus_enumerate_device(xhci_bus_t *bus, xhci_hc_t *hc, device_t *dev)
    54126{
    55127        int err;
    56128        xhci_device_t *xhci_dev = xhci_device_get(dev);
    57 
    58         /* TODO: get speed from the default address reservation */
    59         dev->speed = USB_SPEED_FULL;
    60129
    61130        /* Manage TT */
     
    72141
    73142        /* Assign an address to the device */
    74         if ((err = xhci_rh_address_device(&hc->rh, dev, bus))) {
     143        if ((err = address_device(hc, xhci_dev))) {
    75144                usb_log_error("Failed to setup address of the new device: %s", str_error(err));
    76145                return err;
    77146        }
     147
     148        // TODO: Fetch descriptor of EP0 and reconfigure it accordingly
     149        assert(xhci_dev->endpoints[0]);
    78150
    79151        assert(bus->devices_by_slot[xhci_dev->slot_id] == NULL);
     
    93165}
    94166
     167static int unregister_endpoint(bus_t *, endpoint_t *);
     168
    95169int xhci_bus_remove_device(xhci_bus_t *bus, xhci_hc_t *hc, device_t *dev)
    96170{
     
    98172
    99173        /* Unregister remaining endpoints. */
    100         for (size_t i = 0; i < ARRAY_SIZE(xhci_dev->endpoints); ++i) {
     174        for (unsigned i = 0; i < ARRAY_SIZE(xhci_dev->endpoints); ++i) {
    101175                if (!xhci_dev->endpoints[i])
    102176                        continue;
    103177
    104                 // FIXME: ignoring return code
    105                 bus_unregister_endpoint(&bus->base, &xhci_dev->endpoints[i]->base);
     178                const int err = unregister_endpoint(&bus->base, &xhci_dev->endpoints[i]->base);
     179                if (err)
     180                        usb_log_warning("Failed to unregister EP (%u:%u): %s", dev->address, i, str_error(err));
    106181        }
    107182
     
    167242static int register_endpoint(bus_t *bus_base, endpoint_t *ep, const usb_endpoint_desc_t *desc)
    168243{
     244        int err;
    169245        xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
    170246        assert(bus);
    171247
    172248        assert(ep->device);
    173 
    174         /* Extract USB2-related information from endpoint_desc */
    175         ep->target = (usb_target_t) {{
    176                 .address = ep->device->address,
    177                 .endpoint = desc->endpoint_no,
    178         }};
    179         ep->direction = desc->direction;
    180         ep->transfer_type = desc->transfer_type;
    181         ep->max_packet_size = desc->max_packet_size;
    182         ep->packets = desc->packets;
    183249
    184250        xhci_device_t *xhci_dev = xhci_device_get(ep->device);
    185251        xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep);
    186252
    187         xhci_ep->max_streams = desc->usb3.max_streams;
    188         xhci_ep->max_burst = desc->usb3.max_burst;
    189         // TODO add this property to usb_endpoint_desc_t and fetch it from ss companion desc
    190         xhci_ep->mult = 0;
     253        if ((err = prepare_endpoint(xhci_ep, desc)))
     254                return err;
    191255
    192256        usb_log_info("Endpoint(%d:%d) registered to XHCI bus.", ep->target.address, ep->target.endpoint);
  • uspace/drv/bus/usb/xhci/endpoint.c

    r56db65d r0206d35  
    197197static void setup_control_ep_ctx(xhci_endpoint_t *ep, xhci_ep_ctx_t *ctx)
    198198{
    199         // EP0 is configured elsewhere.
    200         assert(ep->base.target.endpoint > 0);
    201 
    202199        XHCI_EP_TYPE_SET(*ctx, xhci_endpoint_type(ep));
    203200        XHCI_EP_MAX_PACKET_SIZE_SET(*ctx, ep->base.max_packet_size);
     201        XHCI_EP_MAX_BURST_SIZE_SET(*ctx, ep->max_burst);
     202        XHCI_EP_MULT_SET(*ctx, ep->mult);
    204203        XHCI_EP_ERROR_COUNT_SET(*ctx, 3);
    205204        XHCI_EP_TR_DPTR_SET(*ctx, ep->ring.dequeue);
     
    211210        XHCI_EP_TYPE_SET(*ctx, xhci_endpoint_type(ep));
    212211        XHCI_EP_MAX_PACKET_SIZE_SET(*ctx, ep->base.max_packet_size);
    213         XHCI_EP_MAX_BURST_SIZE_SET(*ctx,
    214             xhci_device_get(ep->base.device)->usb3 ? ep->max_burst : 0);
     212        XHCI_EP_MAX_BURST_SIZE_SET(*ctx, ep->max_burst);
    215213        XHCI_EP_ERROR_COUNT_SET(*ctx, 3);
    216214
     
    260258};
    261259
     260void xhci_setup_endpoint_context(xhci_endpoint_t *ep, xhci_ep_ctx_t *ep_ctx)
     261{
     262        assert(ep);
     263        assert(ep_ctx);
     264
     265        usb_transfer_type_t tt = ep->base.transfer_type;
     266        assert(tt < ARRAY_SIZE(setup_ep_ctx_helpers));
     267
     268        memset(ep_ctx, 0, sizeof(*ep_ctx));
     269        setup_ep_ctx_helpers[tt](ep, ep_ctx);
     270}
     271
    262272int xhci_device_add_endpoint(xhci_device_t *dev, xhci_endpoint_t *ep)
    263273{
     
    270280        }
    271281
    272         int err = ENOMEM;
    273282        const usb_endpoint_t ep_num = ep->base.target.endpoint;
    274283
     
    288297        }
    289298
    290         /* Set up TRB ring / PSA. */
    291         if ((err = xhci_endpoint_alloc_transfer_ds(ep))) {
    292                 goto err;
    293         }
    294 
    295299        /* Add endpoint. */
    296300        xhci_ep_ctx_t ep_ctx;
    297         memset(&ep_ctx, 0, sizeof(xhci_ep_ctx_t));
    298         setup_ep_ctx_helpers[ep->base.transfer_type](ep, &ep_ctx);
    299 
    300         if ((err = hc_add_endpoint(dev->hc, dev->slot_id, xhci_endpoint_index(ep), &ep_ctx))) {
    301                 goto err_ds;
    302         }
    303 
    304         return EOK;
    305 
    306 err_ds:
    307         xhci_endpoint_free_transfer_ds(ep);
    308 err:
    309         dev->endpoints[ep_num] = NULL;
    310         dev->active_endpoint_count--;
    311         return err;
     301        xhci_setup_endpoint_context(ep, &ep_ctx);
     302
     303        return hc_add_endpoint(dev->hc, dev->slot_id, xhci_endpoint_index(ep), &ep_ctx);
    312304}
    313305
  • uspace/drv/bus/usb/xhci/endpoint.h

    r56db65d r0206d35  
    119119uint8_t xhci_endpoint_index(xhci_endpoint_t *);
    120120
     121void xhci_setup_endpoint_context(xhci_endpoint_t *, xhci_ep_ctx_t *);
     122
    121123int xhci_device_add_endpoint(xhci_device_t *, xhci_endpoint_t *);
    122124int xhci_device_remove_endpoint(xhci_device_t *, xhci_endpoint_t *);
  • uspace/drv/bus/usb/xhci/hc.c

    r56db65d r0206d35  
    4343#include "rh.h"
    4444#include "hw_struct/trb.h"
     45#include "hw_struct/context.h"
     46#include "endpoint.h"
    4547#include "commands.h"
    4648#include "transfers.h"
     
    449451{
    450452        assert(batch);
     453        assert(batch->ep);
    451454
    452455        usb_log_debug2("Endpoint(%d:%d) started %s transfer of size %lu.",
     
    632635}
    633636
    634 int hc_address_device(xhci_hc_t *hc, uint32_t slot_id, xhci_input_ctx_t *ictx)
    635 {
    636         assert(hc);
    637 
    638         int err;
    639         xhci_cmd_t cmd;
    640         xhci_cmd_init(&cmd);
    641 
    642         cmd.slot_id = slot_id;
    643 
    644         if ((err = xhci_send_address_device_command(hc, &cmd, ictx)) != EOK)
    645                 return err;
    646 
    647         if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT)) != EOK)
    648                 return err;
    649 
    650         xhci_cmd_fini(&cmd);
    651         return EOK;
    652 }
    653 
    654637static int create_valid_input_ctx(xhci_input_ctx_t **out_ictx)
    655638{
     
    674657}
    675658
    676 int hc_address_rh_device(xhci_hc_t *hc, uint32_t slot_id, uint8_t port, xhci_ep_ctx_t *ep_ctx)
     659// TODO: This currently assumes the device is attached to rh directly
     660//      -> calculate route string
     661int hc_address_device(xhci_hc_t *hc, xhci_device_t *dev, xhci_endpoint_t *ep0)
     662{
     663        int err = ENOMEM;
     664
     665        /* Setup and register device context */
     666        dev->dev_ctx = malloc32(sizeof(xhci_device_ctx_t));
     667        if (!dev->dev_ctx)
     668                goto err;
     669        memset(dev->dev_ctx, 0, sizeof(xhci_device_ctx_t));
     670
     671        hc->dcbaa[dev->slot_id] = addr_to_phys(dev->dev_ctx);
     672
     673        /* Issue configure endpoint command (sec 4.3.5). */
     674        xhci_input_ctx_t *ictx;
     675        if ((err = create_valid_input_ctx(&ictx))) {
     676                goto err_dev_ctx;
     677        }
     678
     679        /* Initialize slot_ctx according to section 4.3.3 point 3. */
     680        XHCI_SLOT_ROOT_HUB_PORT_SET(ictx->slot_ctx, dev->base.port); // FIXME: This should be port at RH
     681        XHCI_SLOT_CTX_ENTRIES_SET(ictx->slot_ctx, 1);
     682
     683        /* Attaching to root hub port, root string equals to 0. */
     684        XHCI_SLOT_ROUTE_STRING_SET(ictx->slot_ctx, 0); // FIXME: This is apparently valid in limited cases
     685
     686        /* Copy endpoint 0 context and set A1 flag. */
     687        XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 1);
     688        xhci_setup_endpoint_context(ep0, &ictx->endpoint_ctx[0]);
     689
     690        xhci_cmd_t cmd;
     691        xhci_cmd_init(&cmd);
     692
     693        cmd.slot_id = dev->slot_id;
     694
     695        if ((err = xhci_send_address_device_command(hc, &cmd, ictx)) != EOK)
     696                goto err_cmd;
     697
     698        if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT)) != EOK)
     699                goto err_cmd;
     700
     701        dev->base.address = XHCI_SLOT_DEVICE_ADDRESS(dev->dev_ctx->slot_ctx);
     702        usb_log_debug2("Obtained USB address: %d.\n", dev->base.address);
     703
     704        /* From now on, the device is officially online, yay! */
     705        fibril_mutex_lock(&dev->base.guard);
     706        dev->online = true;
     707        fibril_mutex_unlock(&dev->base.guard);
     708
     709        xhci_cmd_fini(&cmd);
     710        free32(ictx);
     711        return EOK;
     712
     713err_cmd:
     714        xhci_cmd_fini(&cmd);
     715        free32(ictx);
     716err_dev_ctx:
     717        free32(dev->dev_ctx);
     718        hc->dcbaa[dev->slot_id] = 0;
     719err:
     720        return err;
     721}
     722
     723int hc_configure_device(xhci_hc_t *hc, uint32_t slot_id)
    677724{
    678725        int err;
     
    684731        }
    685732
    686         /* Initialize slot_ctx according to section 4.3.3 point 3. */
    687         XHCI_SLOT_ROOT_HUB_PORT_SET(ictx->slot_ctx, port);
    688         XHCI_SLOT_CTX_ENTRIES_SET(ictx->slot_ctx, 1);
    689 
    690         /* Attaching to root hub port, root string equals to 0. */
    691         XHCI_SLOT_ROUTE_STRING_SET(ictx->slot_ctx, 0);
    692 
    693         /* Copy endpoint 0 context and set A1 flag. */
    694         memcpy(&ictx->endpoint_ctx[0], ep_ctx, sizeof(xhci_ep_ctx_t));
    695         XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 1);
    696 
    697         if ((err = hc_address_device(hc, slot_id, ictx))) {
     733        // TODO: Set slot context and other flags. (probably forgot a lot of 'em)
     734
     735        xhci_cmd_t cmd;
     736        xhci_cmd_init(&cmd);
     737
     738        cmd.slot_id = slot_id;
     739
     740        if ((err = xhci_send_configure_endpoint_command(hc, &cmd, ictx))) {
    698741                goto err_cmd;
    699742        }
     743
     744        if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT))) {
     745                goto err_cmd;
     746        }
     747
     748        xhci_cmd_fini(&cmd);
    700749
    701750        free32(ictx);
     
    708757}
    709758
    710 int hc_configure_device(xhci_hc_t *hc, uint32_t slot_id)
     759int hc_deconfigure_device(xhci_hc_t *hc, uint32_t slot_id)
     760{
     761        int err;
     762
     763        /* Issue configure endpoint command (sec 4.3.5) with the DC flag. */
     764        xhci_cmd_t cmd;
     765        xhci_cmd_init(&cmd);
     766
     767        cmd.slot_id = slot_id;
     768        cmd.deconfigure = true;
     769
     770        if ((err = xhci_send_configure_endpoint_command(hc, &cmd, NULL))) {
     771                return err;
     772        }
     773
     774        if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT))) {
     775                return err;
     776        }
     777
     778        xhci_cmd_fini(&cmd);
     779
     780        return EOK;
     781}
     782
     783int hc_add_endpoint(xhci_hc_t *hc, uint32_t slot_id, uint8_t ep_idx, xhci_ep_ctx_t *ep_ctx)
    711784{
    712785        int err;
     
    718791        }
    719792
     793        XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, ep_idx + 1); /* Preceded by slot ctx */
     794        memcpy(&ictx->endpoint_ctx[ep_idx], ep_ctx, sizeof(xhci_ep_ctx_t));
     795
    720796        // TODO: Set slot context and other flags. (probably forgot a lot of 'em)
    721797
     
    744820}
    745821
    746 int hc_deconfigure_device(xhci_hc_t *hc, uint32_t slot_id)
    747 {
    748         int err;
    749 
    750         /* Issue configure endpoint command (sec 4.3.5) with the DC flag. */
    751         xhci_cmd_t cmd;
    752         xhci_cmd_init(&cmd);
    753 
    754         cmd.slot_id = slot_id;
    755         cmd.deconfigure = true;
    756 
    757         if ((err = xhci_send_configure_endpoint_command(hc, &cmd, NULL))) {
    758                 return err;
    759         }
    760 
    761         if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT))) {
    762                 return err;
    763         }
    764 
    765         xhci_cmd_fini(&cmd);
    766 
    767         return EOK;
    768 }
    769 
    770 int hc_add_endpoint(xhci_hc_t *hc, uint32_t slot_id, uint8_t ep_idx, xhci_ep_ctx_t *ep_ctx)
     822int hc_drop_endpoint(xhci_hc_t *hc, uint32_t slot_id, uint8_t ep_idx)
    771823{
    772824        int err;
     
    778830        }
    779831
    780         XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, ep_idx + 1); /* Preceded by slot ctx */
    781         memcpy(&ictx->endpoint_ctx[ep_idx], ep_ctx, sizeof(xhci_ep_ctx_t));
     832        XHCI_INPUT_CTRL_CTX_DROP_SET(ictx->ctrl_ctx, ep_idx + 1); /* Preceded by slot ctx */
    782833
    783834        // TODO: Set slot context and other flags. (probably forgot a lot of 'em)
     
    807858}
    808859
    809 int hc_drop_endpoint(xhci_hc_t *hc, uint32_t slot_id, uint8_t ep_idx)
    810 {
    811         int err;
    812 
    813         /* Issue configure endpoint command (sec 4.3.5). */
    814         xhci_input_ctx_t *ictx;
    815         if ((err = create_valid_input_ctx(&ictx))) {
    816                 goto err;
    817         }
    818 
    819         XHCI_INPUT_CTRL_CTX_DROP_SET(ictx->ctrl_ctx, ep_idx + 1); /* Preceded by slot ctx */
    820 
    821         // TODO: Set slot context and other flags. (probably forgot a lot of 'em)
    822 
    823         xhci_cmd_t cmd;
    824         xhci_cmd_init(&cmd);
    825 
    826         cmd.slot_id = slot_id;
    827 
    828         if ((err = xhci_send_configure_endpoint_command(hc, &cmd, ictx))) {
    829                 goto err_cmd;
    830         }
    831 
    832         if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT))) {
    833                 goto err_cmd;
    834         }
    835 
    836         xhci_cmd_fini(&cmd);
    837 
    838         free32(ictx);
    839         return EOK;
    840 
    841 err_cmd:
    842         free32(ictx);
    843 err:
    844         return err;
    845 }
    846 
    847860/**
    848861 * @}
  • uspace/drv/bus/usb/xhci/hc.h

    r56db65d r0206d35  
    8383} xhci_hc_t;
    8484
     85typedef struct xhci_endpoint xhci_endpoint_t;
     86typedef struct xhci_device xhci_device_t;
     87
    8588int hc_init_mmio(xhci_hc_t *, const hw_res_list_parsed_t *);
    8689int hc_init_memory(xhci_hc_t *, ddf_dev_t *);
     
    9598int hc_enable_slot(xhci_hc_t *, uint32_t *);
    9699int hc_disable_slot(xhci_hc_t *, uint32_t);
    97 int hc_address_device(xhci_hc_t *, uint32_t, xhci_input_ctx_t *);
    98 int hc_address_rh_device(xhci_hc_t *, uint32_t, uint8_t, xhci_ep_ctx_t *);
     100int hc_address_device(xhci_hc_t *, xhci_device_t *, xhci_endpoint_t *);
    99101int hc_configure_device(xhci_hc_t *, uint32_t);
    100102int hc_deconfigure_device(xhci_hc_t *, uint32_t);
  • uspace/drv/bus/usb/xhci/rh.c

    r56db65d r0206d35  
    7474}
    7575
    76 static void setup_control_ep0_ctx(xhci_ep_ctx_t *ctx, xhci_trb_ring_t *ring,
    77                 const xhci_port_speed_t *speed)
    78 {
    79         XHCI_EP_TYPE_SET(*ctx, EP_TYPE_CONTROL);
    80         // TODO: must be changed with a command after USB descriptor is read
    81         // See 4.6.5 in XHCI specification, first note
    82         XHCI_EP_MAX_PACKET_SIZE_SET(*ctx, speed->major == 3 ? 512 : 8);
    83         XHCI_EP_MAX_BURST_SIZE_SET(*ctx, 0);
    84         XHCI_EP_TR_DPTR_SET(*ctx, ring->dequeue);
    85         XHCI_EP_DCS_SET(*ctx, 1);
    86         XHCI_EP_INTERVAL_SET(*ctx, 0);
    87         XHCI_EP_MAX_P_STREAMS_SET(*ctx, 0);
    88         XHCI_EP_MULT_SET(*ctx, 0);
    89         XHCI_EP_ERROR_COUNT_SET(*ctx, 3);
    90 }
    91 
    92 /* FIXME Are these really static? Older HCs fetch it from descriptor. */
    93 /* FIXME Add USB3 options, if applicable. */
    94 static const usb_endpoint_desc_t ep0_desc = {
    95         .endpoint_no = 0,
    96         .direction = USB_DIRECTION_BOTH,
    97         .transfer_type = USB_TRANSFER_CONTROL,
    98         .max_packet_size = CTRL_PIPE_MIN_PACKET_SIZE,
    99         .packets = 1,
    100 };
    101 
    102 // TODO: This currently assumes the device is attached to rh directly.
    103 //       Also, we should consider moving a lot of functionailty to xhci bus
    104 int xhci_rh_address_device(xhci_rh_t *rh, device_t *dev, xhci_bus_t *bus)
    105 {
    106         int err;
    107 
    108         const xhci_port_speed_t *speed = xhci_rh_get_port_speed(rh, dev->port);
    109         xhci_device_t *xhci_dev = xhci_device_get(dev);
    110         xhci_dev->hc = rh->hc;
    111         xhci_dev->usb3 = speed->major == 3;
    112 
    113         /* Enable new slot. */
    114         if ((err = hc_enable_slot(rh->hc, &xhci_dev->slot_id)) != EOK)
    115                 return err;
    116         usb_log_debug2("Obtained slot ID: %u.\n", xhci_dev->slot_id);
    117 
    118         /* Create and configure control endpoint. */
    119         endpoint_t *ep0_base = bus_create_endpoint(&rh->hc->bus.base);
    120         if (!ep0_base)
    121                 return ENOMEM;
    122 
    123         xhci_endpoint_t *ep0 = xhci_endpoint_get(ep0_base);
    124 
    125         if ((err = xhci_endpoint_alloc_transfer_ds(ep0)))
    126                 goto err_ep;
    127 
    128         xhci_ep_ctx_t ep_ctx;
    129         memset(&ep_ctx, 0, sizeof(xhci_ep_ctx_t));
    130         setup_control_ep0_ctx(&ep_ctx, &ep0->ring, speed);
    131 
    132         /* Setup and register device context */
    133         xhci_dev->dev_ctx = malloc32(sizeof(xhci_device_ctx_t));
    134         if (!xhci_dev->dev_ctx) {
    135                 err = ENOMEM;
    136                 goto err_ds;
    137         }
    138         rh->hc->dcbaa[xhci_dev->slot_id] = addr_to_phys(xhci_dev->dev_ctx);
    139         memset(xhci_dev->dev_ctx, 0, sizeof(xhci_device_ctx_t));
    140 
    141         /* Address device */
    142         if ((err = hc_address_rh_device(rh->hc, xhci_dev->slot_id, dev->port, &ep_ctx)))
    143                 goto err_dctx;
    144         dev->address = XHCI_SLOT_DEVICE_ADDRESS(xhci_dev->dev_ctx->slot_ctx);
    145         usb_log_debug2("Obtained USB address: %d.\n", dev->address);
    146 
    147         /* From now on, the device is officially online, yay! */
    148         fibril_mutex_lock(&dev->guard);
    149         xhci_dev->online = true;
    150         fibril_mutex_unlock(&dev->guard);
    151 
    152         ep0_base->device = dev;
    153 
    154         bus_register_endpoint(&rh->hc->bus.base, ep0_base, &ep0_desc);
    155 
    156         if (!rh->devices[dev->port - 1]) {
    157                 /* Only save the device if it's the first one connected to this port. */
    158                 rh->devices[dev->port - 1] = xhci_dev;
    159         }
    160 
    161         return EOK;
    162 
    163 err_dctx:
    164         free32(xhci_dev->dev_ctx);
    165         rh->hc->dcbaa[xhci_dev->slot_id] = 0;
    166 err_ds:
    167         xhci_endpoint_free_transfer_ds(ep0);
    168 err_ep:
    169         xhci_endpoint_fini(ep0);
    170         free(ep0);
    171         return err;
     76static usb_speed_t port_speed_to_usb_speed(const xhci_port_speed_t *port_speed)
     77{
     78        assert(port_speed->major > 0 && port_speed->major <= USB_SPEED_SUPER);
     79
     80        switch (port_speed->major) {
     81                case 3: return USB_SPEED_SUPER;
     82                case 2: return USB_SPEED_HIGH;
     83                case 1: return port_speed->minor ? USB_SPEED_FULL : USB_SPEED_LOW;
     84        }
     85
     86        assert(false);
    17287}
    17388
     
    188103        }
    189104
     105        const xhci_port_speed_t *port_speed = xhci_rh_get_port_speed(rh, port_id);
     106        xhci_device_t *xhci_dev = xhci_device_get(dev);
     107        xhci_dev->hc = rh->hc;
     108        xhci_dev->usb3 = port_speed->major == 3;
     109
    190110        dev->hub = &rh->device;
    191111        dev->port = port_id;
     112        dev->speed = port_speed_to_usb_speed(port_speed);
    192113
    193114        if ((err = xhci_bus_enumerate_device(bus, rh->hc, dev))) {
     
    207128        fibril_mutex_lock(&rh->device.guard);
    208129        list_append(&dev->link, &rh->device.devices);
     130        if (!rh->devices[port_id - 1]) {
     131                /* Only save the device if it's the first one connected to this port. */
     132                rh->devices[port_id - 1] = xhci_dev;
     133        }
    209134        fibril_mutex_unlock(&rh->device.guard);
    210135
     
    286211                        continue;
    287212
     213                /* FIXME: This is racy. */
    288214                if ((err = xhci_transfer_abort(&ep->active_transfer))) {
    289215                        usb_log_warning("Failed to abort active %s transfer to "
     
    305231
    306232        /* Unregister EP0. */
    307         if ((err = bus_unregister_endpoint(&rh->hc->bus.base, &dev->endpoints[0]->base))) {
     233        if ((err = bus_remove_endpoint(&rh->hc->bus.base, &dev->endpoints[0]->base))) {
    308234                usb_log_warning("Failed to unregister configuration endpoint of device '%s' from XHCI bus: %s",
    309235                    ddf_fun_get_name(dev->base.fun), str_error(err));
  • uspace/lib/usbhost/include/usb/host/bus.h

    r56db65d r0206d35  
    117117int device_init(device_t *);
    118118
    119 extern int bus_add_ep(bus_t *, device_t *, const usb_endpoint_desc_t *);
    120 extern int bus_remove_ep(bus_t *, device_t *, usb_target_t, usb_direction_t);
    121 
    122119int device_set_default_name(device_t *);
    123120
     
    125122int bus_remove_device(bus_t *, hcd_t *, device_t *);
    126123
    127 endpoint_t *bus_create_endpoint(bus_t *);
    128 int bus_register_endpoint(bus_t *, endpoint_t *, const usb_endpoint_desc_t *);
    129 int bus_unregister_endpoint(bus_t *, endpoint_t *);
     124int bus_add_endpoint(bus_t *, device_t *, const usb_endpoint_desc_t *, endpoint_t **);
    130125endpoint_t *bus_find_endpoint(bus_t *, device_t *, usb_target_t, usb_direction_t);
     126int bus_remove_endpoint(bus_t *, endpoint_t *);
    131127
    132128size_t bus_count_bw(endpoint_t *, size_t);
  • uspace/lib/usbhost/src/bus.c

    r56db65d r0206d35  
    6666}
    6767
    68 int bus_add_ep(bus_t *bus, device_t *device, const usb_endpoint_desc_t *desc)
    69 {
    70         assert(bus);
    71         assert(device);
    72 
    73         /* Temporary reference */
    74         endpoint_t *ep = bus_create_endpoint(bus);
    75         if (!ep)
    76                 return ENOMEM;
    77 
    78         ep->device = device;
    79         const int err = bus_register_endpoint(bus, ep, desc);
    80 
    81         /* drop Temporary reference */
    82         endpoint_del_ref(ep);
    83 
    84         return err;
    85 }
    86 
    87 int bus_remove_ep(bus_t *bus, device_t *dev, usb_target_t target, usb_direction_t dir)
    88 {
    89         assert(bus);
    90         endpoint_t *ep = bus_find_endpoint(bus, dev, target, dir);
    91         if (!ep)
    92                 return ENOENT;
    93 
    94         return bus_unregister_endpoint(bus, ep);
    95 }
    96 
    9768int device_set_default_name(device_t *dev)
    9869{
     
    136107}
    137108
    138 endpoint_t *bus_create_endpoint(bus_t *bus)
    139 {
    140         assert(bus);
    141 
    142         fibril_mutex_lock(&bus->guard);
     109int bus_add_endpoint(bus_t *bus, device_t *device, const usb_endpoint_desc_t *desc, endpoint_t **out_ep)
     110{
     111        int err = ENOMEM;
     112
     113        assert(bus);
     114        assert(device);
     115
     116        fibril_mutex_lock(&bus->guard);
     117
    143118        endpoint_t *ep = bus->ops.create_endpoint(bus);
    144         if (ep) {
    145                 /* Exporting reference */
    146                 endpoint_add_ref(ep);
    147         }
    148         fibril_mutex_unlock(&bus->guard);
    149 
    150         return ep;
    151 }
    152 
    153 int bus_register_endpoint(bus_t *bus, endpoint_t *ep, const usb_endpoint_desc_t *desc)
    154 {
    155         assert(bus);
    156         assert(ep);
     119        if (!ep)
     120                goto err;
    157121
    158122        /* Bus reference */
    159123        endpoint_add_ref(ep);
    160124
    161         fibril_mutex_lock(&bus->guard);
    162         const int r = bus->ops.register_endpoint(bus, ep, desc);
    163         fibril_mutex_unlock(&bus->guard);
    164 
    165         return r;
    166 }
    167 
    168 int bus_unregister_endpoint(bus_t *bus, endpoint_t *ep)
    169 {
    170         assert(bus);
    171         assert(ep);
    172 
    173         fibril_mutex_lock(&bus->guard);
    174         const int r = bus->ops.unregister_endpoint(bus, ep);
    175         fibril_mutex_unlock(&bus->guard);
    176 
    177         if (r)
    178                 return r;
    179 
    180         /* Bus reference */
     125        ep->device = device;
     126        if ((err = bus->ops.register_endpoint(bus, ep, desc)))
     127                goto err_ep;
     128
     129        if (out_ep) {
     130                endpoint_add_ref(ep);
     131                *out_ep = ep;
     132        }
     133
     134        fibril_mutex_unlock(&bus->guard);
     135        return EOK;
     136
     137err_ep:
    181138        endpoint_del_ref(ep);
    182 
    183         return EOK;
     139err:
     140        fibril_mutex_unlock(&bus->guard);
     141        return err;
    184142}
    185143
     
    201159}
    202160
     161int bus_remove_endpoint(bus_t *bus, endpoint_t *ep)
     162{
     163        assert(bus);
     164        assert(ep);
     165
     166        fibril_mutex_lock(&bus->guard);
     167        const int r = bus->ops.unregister_endpoint(bus, ep);
     168        fibril_mutex_unlock(&bus->guard);
     169
     170        if (r)
     171                return r;
     172
     173        /* Bus reference */
     174        endpoint_del_ref(ep);
     175
     176        return EOK;
     177}
     178
    203179int bus_request_address(bus_t *bus, usb_address_t *hint, bool strict, usb_speed_t speed)
    204180{
  • uspace/lib/usbhost/src/ddf_helpers.c

    r56db65d r0206d35  
    104104                endpoint_desc->max_packet_size, endpoint_desc->usb2.polling_interval);
    105105
    106         return bus_add_ep(hcd->bus, dev, endpoint_desc);
     106        return bus_add_endpoint(hcd->bus, dev, endpoint_desc, NULL);
    107107}
    108108
     
    130130                dev->address, endpoint_desc->endpoint_no,
    131131                usb_str_direction(endpoint_desc->direction));
    132         return bus_remove_ep(hcd->bus, dev, target, endpoint_desc->direction);
     132
     133        endpoint_t *ep = bus_find_endpoint(hcd->bus, dev, target, endpoint_desc->direction);
     134        if (!ep)
     135                return ENOENT;
     136
     137        return bus_remove_endpoint(hcd->bus, ep);
    133138}
    134139
  • uspace/lib/usbhost/src/usb2_bus.c

    r56db65d r0206d35  
    120120        /* Add default pipe on default address */
    121121        usb_log_debug("Device(%d): Adding default target (0:0)", address);
    122         err = bus_add_ep(bus, dev, &usb2_default_control_ep);
     122
     123        endpoint_t *default_ep;
     124        err = bus_add_endpoint(bus, dev, &usb2_default_control_ep, &default_ep);
    123125        if (err != EOK) {
    124126                usb_log_error("Device(%d): Failed to add default target: %s.",
     
    169171        /* Register EP on the new address */
    170172        usb_log_debug("Device(%d): Registering control EP.", address);
    171         err = bus_add_ep(bus, dev, &control_ep);
     173        err = bus_add_endpoint(bus, dev, &control_ep, NULL);
    172174        if (err != EOK) {
    173175                usb_log_error("Device(%d): Failed to register EP0: %s",
     
    176178        }
    177179
    178         bus_remove_ep(bus, dev, usb2_default_target, USB_DIRECTION_BOTH);
     180        err = bus_remove_endpoint(bus, default_ep);
     181        assert(err == EOK);
     182        endpoint_del_ref(default_ep);
     183
     184        err = bus_release_address(bus, address);
     185        assert(err == EOK);
     186
    179187        return EOK;
    180188
    181189err_default_control_ep:
    182         bus_remove_ep(bus, dev, usb2_default_target, USB_DIRECTION_BOTH);
     190        bus_remove_endpoint(bus, default_ep);
     191        endpoint_del_ref(default_ep);
    183192err_address:
    184193        bus_release_address(bus, address);
Note: See TracChangeset for help on using the changeset viewer.