Changeset 2b61945 in mainline for uspace/drv/bus/usb/xhci/endpoint.c


Ignore:
Timestamp:
2017-10-22T03:47:41Z (7 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2e5aea1
Parents:
766043c
Message:

xhci: use device_t for bookkeeping

This started as a little refactoring to move active transfer batch to endpoint. Finding the EP in handler needs devices indexed by slot id. Then I found out we do not use the device_t extendable mechanism. Then there were a lot of errors found while doing all this…

File:
1 edited

Legend:

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

    r766043c r2b61945  
    5353
    5454        endpoint_init(ep, bus);
    55         xhci_ep->device = NULL;
    56 
    57         return EOK;
     55
     56        return xhci_trb_ring_init(&xhci_ep->ring);
    5857}
    5958
     
    6362
    6463        /* FIXME: Tear down TR's? */
    65 }
    66 
    67 int xhci_device_init(xhci_device_t *dev, xhci_bus_t *bus, usb_address_t address)
    68 {
    69         memset(&dev->endpoints, 0, sizeof(dev->endpoints));
    70         dev->active_endpoint_count = 0;
    71         dev->address = address;
    72         dev->slot_id = 0;
    73 
    74         return EOK;
    75 }
    76 
    77 void xhci_device_fini(xhci_device_t *dev)
    78 {
    79         // TODO: Check that all endpoints are dead.
    80         assert(dev);
     64        xhci_trb_ring_fini(&xhci_ep->ring);
     65}
     66
     67/** See section 4.5.1 of the xHCI spec.
     68 */
     69uint8_t xhci_endpoint_dci(xhci_endpoint_t *ep)
     70{
     71        return (2 * ep->base.target.endpoint) +
     72                (ep->base.transfer_type == USB_TRANSFER_CONTROL
     73                 || ep->base.direction == USB_DIRECTION_IN);
    8174}
    8275
     
    9386uint8_t xhci_endpoint_index(xhci_endpoint_t *ep)
    9487{
    95         return  (2 * ep->base.target.endpoint)
    96             - (ep->base.direction == USB_DIRECTION_OUT);
     88        return xhci_endpoint_dci(ep) - 1;
    9789}
    9890
     
    139131        XHCI_EP_TYPE_SET(*ctx, xhci_endpoint_type(ep));
    140132        XHCI_EP_MAX_PACKET_SIZE_SET(*ctx, ep->base.max_packet_size);
    141         XHCI_EP_MAX_BURST_SIZE_SET(*ctx, ep->device->usb3 ? ss_desc->max_burst : 0);
     133        XHCI_EP_MAX_BURST_SIZE_SET(*ctx,
     134            xhci_device_get(ep->base.device)->usb3 ? ss_desc->max_burst : 0);
    142135        XHCI_EP_ERROR_COUNT_SET(*ctx, 3);
    143136
     
    186179int xhci_device_add_endpoint(xhci_device_t *dev, xhci_endpoint_t *ep)
    187180{
    188         assert(dev->address == ep->base.target.address);
    189         assert(!dev->endpoints[ep->base.target.endpoint]);
    190         assert(!ep->device);
    191 
    192         int err;
    193         xhci_input_ctx_t *ictx = NULL;
    194         xhci_trb_ring_t *ep_ring = NULL;
    195         if (ep->base.target.endpoint > 0) {
    196                 // FIXME: Retrieve this from somewhere, if applicable.
    197                 usb_superspeed_endpoint_companion_descriptor_t ss_desc;
    198                 memset(&ss_desc, 0, sizeof(ss_desc));
    199 
    200                 // Prepare input context.
    201                 ictx = malloc32(sizeof(xhci_input_ctx_t));
    202                 if (!ictx) {
    203                         return ENOMEM;
    204                 }
    205 
    206                 memset(ictx, 0, sizeof(xhci_input_ctx_t));
    207 
    208                 // Quoting sec. 4.6.6: A1, D0, D1 are down, A0 is up.
    209                 XHCI_INPUT_CTRL_CTX_ADD_CLEAR(ictx->ctrl_ctx, 1);
    210                 XHCI_INPUT_CTRL_CTX_DROP_CLEAR(ictx->ctrl_ctx, 0);
    211                 XHCI_INPUT_CTRL_CTX_DROP_CLEAR(ictx->ctrl_ctx, 1);
    212                 XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 0);
    213 
    214                 const uint8_t ep_idx = xhci_endpoint_index(ep);
    215                 XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, ep_idx + 1); /* Preceded by slot ctx */
    216 
    217                 ep_ring = malloc(sizeof(xhci_trb_ring_t));
    218                 if (!ep_ring) {
    219                         err = ENOMEM;
    220                         goto err_ictx;
    221                 }
    222 
    223                 // FIXME: This ring need not be allocated all the time.
    224                 err = xhci_trb_ring_init(ep_ring);
    225                 if (err)
    226                         goto err_ring;
    227 
    228                 switch (ep->base.transfer_type) {
    229                 case USB_TRANSFER_CONTROL:
    230                         setup_control_ep_ctx(ep, &ictx->endpoint_ctx[ep_idx], ep_ring);
    231                         break;
    232 
    233                 case USB_TRANSFER_BULK:
    234                         setup_bulk_ep_ctx(ep, &ictx->endpoint_ctx[ep_idx], ep_ring, &ss_desc);
    235                         break;
    236 
    237                 case USB_TRANSFER_ISOCHRONOUS:
    238                         setup_isoch_ep_ctx(ep, &ictx->endpoint_ctx[ep_idx], ep_ring, &ss_desc);
    239                         break;
    240 
    241                 case USB_TRANSFER_INTERRUPT:
    242                         setup_interrupt_ep_ctx(ep, &ictx->endpoint_ctx[ep_idx], ep_ring, &ss_desc);
    243                         break;
    244 
    245                 }
    246 
    247                 dev->hc->dcbaa_virt[dev->slot_id].trs[ep->base.target.endpoint] = ep_ring;
    248 
    249                 // Issue configure endpoint command (sec 4.3.5).
    250                 xhci_cmd_t cmd;
    251                 xhci_cmd_init(&cmd);
    252 
    253                 cmd.slot_id = dev->slot_id;
    254                 xhci_send_configure_endpoint_command(dev->hc, &cmd, ictx);
    255                 if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT)) != EOK)
    256                         goto err_cmd;
    257 
    258                 xhci_cmd_fini(&cmd);
     181        assert(dev);
     182        assert(ep);
     183
     184        int err = ENOMEM;
     185        usb_endpoint_t ep_num = ep->base.target.endpoint;
     186
     187        assert(&dev->base == ep->base.device);
     188        assert(dev->base.address == ep->base.target.address);
     189        assert(!dev->endpoints[ep_num]);
     190
     191        dev->endpoints[ep_num] = ep;
     192        ++dev->active_endpoint_count;
     193
     194        if (ep_num == 0)
     195                /* EP 0 is initialized while setting up the device,
     196                 * so we must not issue the command now. */
     197                return EOK;
     198
     199        // FIXME: Retrieve this from somewhere, if applicable.
     200        usb_superspeed_endpoint_companion_descriptor_t ss_desc;
     201        memset(&ss_desc, 0, sizeof(ss_desc));
     202
     203        // Prepare input context.
     204        xhci_input_ctx_t *ictx = malloc32(sizeof(xhci_input_ctx_t));
     205        if (!ictx)
     206                goto err;
     207
     208        memset(ictx, 0, sizeof(xhci_input_ctx_t));
     209
     210        // Quoting sec. 4.6.6: A1, D0, D1 are down, A0 is up.
     211        XHCI_INPUT_CTRL_CTX_ADD_CLEAR(ictx->ctrl_ctx, 1);
     212        XHCI_INPUT_CTRL_CTX_DROP_CLEAR(ictx->ctrl_ctx, 0);
     213        XHCI_INPUT_CTRL_CTX_DROP_CLEAR(ictx->ctrl_ctx, 1);
     214        XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 0);
     215
     216        unsigned ep_idx = xhci_endpoint_index(ep);
     217        XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, ep_idx + 1); /* Preceded by slot ctx */
     218
     219        xhci_trb_ring_t *ep_ring = &ep->ring;
     220        xhci_ep_ctx_t *ep_ctx = &ictx->endpoint_ctx[ep_idx];
     221
     222        // TODO: Convert to table
     223        switch (ep->base.transfer_type) {
     224        case USB_TRANSFER_CONTROL:
     225                setup_control_ep_ctx(ep, ep_ctx, ep_ring);
     226                break;
     227
     228        case USB_TRANSFER_BULK:
     229                setup_bulk_ep_ctx(ep, ep_ctx, ep_ring, &ss_desc);
     230                break;
     231
     232        case USB_TRANSFER_ISOCHRONOUS:
     233                setup_isoch_ep_ctx(ep, ep_ctx, ep_ring, &ss_desc);
     234                break;
     235
     236        case USB_TRANSFER_INTERRUPT:
     237                setup_interrupt_ep_ctx(ep, ep_ctx, ep_ring, &ss_desc);
     238                break;
    259239        }
    260240
    261         ep->device = dev;
    262         dev->endpoints[ep->base.target.endpoint] = ep;
    263         ++dev->active_endpoint_count;
     241        // Issue configure endpoint command (sec 4.3.5).
     242        xhci_cmd_t cmd;
     243        xhci_cmd_init(&cmd);
     244
     245        cmd.slot_id = dev->slot_id;
     246        xhci_send_configure_endpoint_command(dev->hc, &cmd, ictx);
     247        if ((err = xhci_cmd_wait(&cmd, XHCI_DEFAULT_TIMEOUT)) != EOK)
     248                goto err_ictx;
     249
     250        xhci_cmd_fini(&cmd);
     251
     252        free32(ictx);
    264253        return EOK;
    265254
    266 err_cmd:
    267 err_ring:
    268         if (ep_ring) {
    269                 xhci_trb_ring_fini(ep_ring);
    270                 free(ep_ring);
    271         }
    272255err_ictx:
    273         free(ictx);
     256        free32(ictx);
     257err:
     258        dev->endpoints[ep_idx] = NULL;
     259        dev->active_endpoint_count--;
    274260        return err;
    275261}
     
    277263int xhci_device_remove_endpoint(xhci_device_t *dev, xhci_endpoint_t *ep)
    278264{
    279         assert(dev->address == ep->base.target.address);
     265        assert(&dev->base == ep->base.device);
     266        assert(dev->base.address == ep->base.target.address);
    280267        assert(dev->endpoints[ep->base.target.endpoint]);
    281         assert(dev == ep->device);
    282268
    283269        // TODO: Issue configure endpoint command to drop this endpoint.
    284270
    285         ep->device = NULL;
    286271        dev->endpoints[ep->base.target.endpoint] = NULL;
    287272        --dev->active_endpoint_count;
Note: See TracChangeset for help on using the changeset viewer.