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

Changeset 2b61945 in mainline


Ignore:
Timestamp:
2017-10-22T03:47:41Z (3 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
master
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…

Location:
uspace
Files:
14 edited

Legend:

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

    r766043c r2b61945  
    3535#include <adt/hash_table.h>
    3636#include <adt/hash.h>
     37#include <usb/host/utils/malloc32.h>
    3738#include <usb/host/ddf_helpers.h>
    3839#include <usb/host/endpoint.h>
     
    5859} hashed_device_t;
    5960
     61static int hashed_device_insert(xhci_bus_t *bus, hashed_device_t **hashed_dev, xhci_device_t *dev);
     62static int hashed_device_remove(xhci_bus_t *bus, hashed_device_t *hashed_dev);
     63static int hashed_device_find_by_address(xhci_bus_t *bus, usb_address_t address, hashed_device_t **dev);
     64
    6065/** TODO: Still some copy-pasta left...
    6166 */
     
    6368{
    6469        int err;
     70        xhci_device_t *xhci_dev = xhci_device_get(dev);
    6571
    6672        /* TODO: get speed from the default address reservation */
     
    8591        }
    8692
     93        assert(bus->devices_by_slot[xhci_dev->slot_id] == NULL);
     94        bus->devices_by_slot[xhci_dev->slot_id] = xhci_dev;
     95
     96        hashed_device_t *hashed_dev = NULL;
     97        if ((err = hashed_device_insert(bus, &hashed_dev, xhci_dev)))
     98                goto err_address;
     99
    87100        /* Read the device descriptor, derive the match ids */
    88101        if ((err = hcd_ddf_device_explore(hc->hcd, dev))) {
    89102                usb_log_error("Device(%d): Failed to explore device: %s", dev->address, str_error(err));
    90                 bus_release_address(&bus->base, dev->address);
    91                 return err;
    92         }
    93 
    94         return EOK;
     103                goto err_hash;
     104        }
     105
     106        return EOK;
     107
     108err_hash:
     109        bus->devices_by_slot[xhci_dev->slot_id] = NULL;
     110        hashed_device_remove(bus, hashed_dev);
     111err_address:
     112        bus_release_address(&bus->base, dev->address);
     113        return err;
    95114}
    96115
    97116int xhci_bus_remove_device(xhci_bus_t *bus, xhci_hc_t *hc, device_t *dev)
    98117{
    99         // TODO: Implement me!
     118        xhci_device_t *xhci_dev = xhci_device_get(dev);
     119
     120        // TODO: Release remaining EPs
     121
     122        hashed_device_t *hashed_dev;
     123        int res = hashed_device_find_by_address(bus, dev->address, &hashed_dev);
     124        if (res)
     125                return res;
     126
     127        res = hashed_device_remove(bus, hashed_dev);
     128        if (res != EOK)
     129                return res;
     130
     131        // XXX: Ugly here. Move to device_destroy at endpoint.c?
     132        free32(xhci_dev->dev_ctx);
     133        hc->dcbaa[xhci_dev->slot_id] = 0;
    100134        return ENOTSUP;
    101135}
     
    134168        xhci_bus_t *bus = bus_to_xhci_bus(base);
    135169
    136         xhci_endpoint_t *ep = malloc(sizeof(xhci_endpoint_t));
     170        xhci_endpoint_t *ep = calloc(1, sizeof(xhci_endpoint_t));
    137171        if (!ep)
    138172                return NULL;
     
    179213}
    180214
    181 static int hashed_device_create(xhci_bus_t *bus, hashed_device_t **hashed_dev, usb_address_t address)
    182 {
    183         int res;
    184         xhci_device_t *dev = (xhci_device_t *) malloc(sizeof(xhci_device_t));
    185         if (!dev) {
    186                 res = ENOMEM;
    187                 goto err_xhci_dev_alloc;
    188         }
    189 
    190         res = xhci_device_init(dev, bus, address);
    191         if (res != EOK) {
    192                 goto err_xhci_dev_init;
    193         }
    194 
    195         hashed_device_t *ret_dev = (hashed_device_t *) malloc(sizeof(hashed_device_t));
    196         if (!ret_dev) {
    197                 res = ENOMEM;
    198                 goto err_hashed_dev_alloc;
    199         }
     215static int hashed_device_insert(xhci_bus_t *bus, hashed_device_t **hashed_dev, xhci_device_t *dev)
     216{
     217        hashed_device_t *ret_dev = (hashed_device_t *) calloc(1, sizeof(hashed_device_t));
     218        if (!ret_dev)
     219                return ENOMEM;
    200220
    201221        ret_dev->device = dev;
    202222
    203         usb_log_info("Device(%d) registered to XHCI bus.", dev->address);
     223        usb_log_info("Device(%d) registered to XHCI bus.", dev->base.address);
    204224
    205225        hash_table_insert(&bus->devices, &ret_dev->link);
    206226        *hashed_dev = ret_dev;
    207227        return EOK;
    208 
    209 err_hashed_dev_alloc:
    210 err_xhci_dev_init:
    211         free(dev);
    212 err_xhci_dev_alloc:
    213         return res;
    214228}
    215229
    216230static int hashed_device_remove(xhci_bus_t *bus, hashed_device_t *hashed_dev)
    217231{
    218         usb_log_info("Device(%d) released from XHCI bus.", hashed_dev->device->address);
    219 
    220         hash_table_remove(&bus->devices, &hashed_dev->device->address);
    221         xhci_device_fini(hashed_dev->device);
    222         free(hashed_dev->device);
     232        usb_log_info("Device(%d) released from XHCI bus.", hashed_dev->device->base.address);
     233
     234        hash_table_remove(&bus->devices, &hashed_dev->device->base.address);
    223235        free(hashed_dev);
    224236
     
    231243        assert(bus);
    232244
    233         hashed_device_t *hashed_dev;
    234         int res = hashed_device_find_by_address(bus, ep->target.address, &hashed_dev);
    235         if (res != EOK && res != ENOENT)
    236                 return res;
    237 
    238         if (res == ENOENT) {
    239                 res = hashed_device_create(bus, &hashed_dev, ep->target.address);
    240 
    241                 if (res != EOK)
    242                         return res;
    243         }
    244 
    245245        usb_log_info("Endpoint(%d:%d) registered to XHCI bus.", ep->target.address, ep->target.endpoint);
    246246
    247         return xhci_device_add_endpoint(hashed_dev->device, xhci_endpoint_get(ep));
     247        xhci_device_t *xhci_dev = xhci_device_get(ep->device);
     248        xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep);
     249        return xhci_device_add_endpoint(xhci_dev, xhci_ep);
    248250}
    249251
     
    255257        usb_log_info("Endpoint(%d:%d) released from XHCI bus.", ep->target.address, ep->target.endpoint);
    256258
    257         hashed_device_t *hashed_dev;
    258         int res = hashed_device_find_by_address(bus, ep->target.address, &hashed_dev);
     259        xhci_device_t *xhci_dev = xhci_device_get(ep->device);
     260        xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep);
     261        const int res = xhci_device_remove_endpoint(xhci_dev, xhci_ep);
    259262        if (res != EOK)
    260263                return res;
    261264
    262         res = xhci_device_remove_endpoint(hashed_dev->device, xhci_endpoint_get(ep));
    263         if (res != EOK)
    264                 return res;
    265 
    266         if (hashed_dev->device->active_endpoint_count == 0) {
    267                 res = hashed_device_remove(bus, hashed_dev);
    268 
    269                 if (res != EOK)
    270                         return res;
    271         }
    272 
    273265        return EOK;
    274266}
     
    278270        xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
    279271        assert(bus);
    280 
     272       
    281273        xhci_endpoint_t *ep;
    282274        int res = xhci_endpoint_find_by_target(bus, target, &ep);
     
    349341{
    350342        hashed_device_t *dev = hash_table_get_inst(item, hashed_device_t, link);
    351         return (size_t) hash_mix(dev->device->address);
     343        return (size_t) hash_mix(dev->device->base.address);
    352344}
    353345
     
    360352{
    361353        hashed_device_t *dev = hash_table_get_inst(item, hashed_device_t, link);
    362         return dev->device->address == *(usb_address_t *) key;
     354        return dev->device->base.address == *(usb_address_t *) key;
    363355}
    364356
     
    372364};
    373365
    374 int xhci_bus_init(xhci_bus_t *bus)
    375 {
    376         assert(bus);
    377 
    378         bus_init(&bus->base, sizeof(device_t));
     366int xhci_bus_init(xhci_bus_t *bus, xhci_hc_t *hc)
     367{
     368        assert(bus);
     369
     370        bus_init(&bus->base, sizeof(xhci_device_t));
     371
     372        bus->devices_by_slot = calloc(hc->max_slots, sizeof(xhci_device_t *));
     373        if (!bus->devices_by_slot)
     374                return ENOMEM;
    379375
    380376        if (!hash_table_create(&bus->devices, 0, 0, &device_ht_ops)) {
    381                 // FIXME: Dealloc base!
     377                free(bus->devices_by_slot);
    382378                return ENOMEM;
    383379        }
  • uspace/drv/bus/usb/xhci/bus.h

    r766043c r2b61945  
    4343
    4444typedef struct xhci_hc xhci_hc_t;
     45typedef struct xhci_device xhci_device_t;
    4546
    4647/** Endpoint management structure */
     
    4849        bus_t base;             /**< Inheritance. Keep this first. */
    4950
    50         /** TODO: some mechanism to keep endpoints alive :)
    51          * We may inspire in the usb2_bus, but keep in mind xHCI have much
    52          * larger address space, thus simple array of lists for all available
    53          * addresses can be just too big.
    54          */
     51        xhci_device_t **devices_by_slot;        /**< Devices by Slot ID */
    5552
    56         hash_table_t devices;
     53        /** TODO: Do we really need this? */
     54        hash_table_t devices;           /**< Devices by address */
    5755} xhci_bus_t;
    5856
    59 int xhci_bus_init(xhci_bus_t *);
     57int xhci_bus_init(xhci_bus_t *, xhci_hc_t *);
    6058void xhci_bus_fini(xhci_bus_t *);
    6159
  • 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;
  • uspace/drv/bus/usb/xhci/endpoint.h

    r766043c r2b61945  
    4444
    4545#include "hc.h"
     46#include "transfers.h"
    4647
    4748typedef struct xhci_device xhci_device_t;
     
    6465        endpoint_t base;        /**< Inheritance. Keep this first. */
    6566
    66         /** Parent device. */
    67         xhci_device_t *device;
     67        /** Main TRB ring */
     68        xhci_trb_ring_t ring;
     69
     70        /** There shall be only one transfer active on an endpoint. The
     71         * synchronization is performed using the active flag in base
     72         * endpoint_t */
     73        xhci_transfer_t active_transfer;
    6874} xhci_endpoint_t;
    6975
    7076typedef struct xhci_device {
    71         /** Unique USB address assigned to the device. */
    72         usb_address_t address;
     77        device_t base;          /**< Inheritance. Keep this first. */
    7378
    7479        /** Slot ID assigned to the device by xHC. */
    7580        uint32_t slot_id;
    7681
    77         /** Associated device in libusbhost. */
    78         device_t *device;
     82        /** Place to store virtual address for allocated context */
     83        xhci_device_ctx_t *dev_ctx;
    7984
    8085        /** All endpoints of the device. Inactive ones are NULL */
     
    97102void xhci_device_fini(xhci_device_t *);
    98103
     104uint8_t xhci_endpoint_dci(xhci_endpoint_t *);
    99105uint8_t xhci_endpoint_index(xhci_endpoint_t *);
    100106
     
    104110int xhci_device_configure(xhci_device_t *, xhci_hc_t *);
    105111
     112static inline xhci_device_t * xhci_device_get(device_t *dev)
     113{
     114        assert(dev);
     115        return (xhci_device_t *) dev;
     116}
     117
    106118static inline xhci_endpoint_t * xhci_endpoint_get(endpoint_t *ep)
    107119{
    108120        assert(ep);
    109121        return (xhci_endpoint_t *) ep;
     122}
     123
     124static inline xhci_device_t * xhci_ep_to_dev(xhci_endpoint_t *ep)
     125{
     126        assert(ep);
     127        return xhci_device_get(ep->base.device);
    110128}
    111129
  • uspace/drv/bus/usb/xhci/hc.c

    r766043c r2b61945  
    196196                return ENOMEM;
    197197
    198         hc->dcbaa_virt = malloc((1 + hc->max_slots) * sizeof(xhci_virt_device_ctx_t));
    199         if (!hc->dcbaa_virt) {
    200                 err = ENOMEM;
     198        if ((err = xhci_trb_ring_init(&hc->command_ring)))
    201199                goto err_dcbaa;
    202         }
    203 
    204         if ((err = xhci_trb_ring_init(&hc->command_ring)))
    205                 goto err_dcbaa_virt;
    206200
    207201        if ((err = xhci_event_ring_init(&hc->event_ring)))
     
    214208                goto err_scratch;
    215209
    216         if ((err = xhci_init_transfers(hc)))
     210        if ((err = xhci_rh_init(&hc->rh, hc, device)))
    217211                goto err_cmd;
    218212
    219         if ((err = xhci_rh_init(&hc->rh, hc, device)))
    220                 goto err_transfers;
    221 
    222         if ((err = xhci_bus_init(&hc->bus)))
     213        if ((err = xhci_bus_init(&hc->bus, hc)))
    223214                goto err_rh;
    224215
     
    228219err_rh:
    229220        xhci_rh_fini(&hc->rh);
    230 err_transfers:
    231         xhci_fini_transfers(hc);
    232221err_cmd:
    233222        xhci_fini_commands(hc);
     
    238227err_cmd_ring:
    239228        xhci_trb_ring_fini(&hc->command_ring);
    240 err_dcbaa_virt:
    241         free32(hc->dcbaa_virt);
    242229err_dcbaa:
    243230        free32(hc->dcbaa);
     
    527514        /* Update the ERDP to make room in the ring. */
    528515        usb_log_debug2("Copying from ring finished, updating ERDP.");
    529         hc->event_ring.dequeue_ptr = host2xhci(64, addr_to_phys(hc->event_ring.dequeue_trb));
    530516        uint64_t erdp = hc->event_ring.dequeue_ptr;
    531517        XHCI_REG_WR(intr, XHCI_INTR_ERDP_LO, LOWER32(erdp));
     
    580566static void hc_dcbaa_fini(xhci_hc_t *hc)
    581567{
    582         xhci_trb_ring_t* trb_ring;
    583568        xhci_scratchpad_free(hc);
    584 
    585         /* Idx 0 already deallocated by xhci_scratchpad_free. */
    586         for (unsigned i = 1; i < hc->max_slots + 1; ++i) {
    587                 if (hc->dcbaa_virt[i].dev_ctx) {
    588                         free32(hc->dcbaa_virt[i].dev_ctx);
    589                         hc->dcbaa_virt[i].dev_ctx = NULL;
    590                 }
    591 
    592                 for (unsigned i = 0; i < XHCI_EP_COUNT; ++i) {
    593                         trb_ring = hc->dcbaa_virt[i].trs[i];
    594                         if (trb_ring) {
    595                                 hc->dcbaa_virt[i].trs[i] = NULL;
    596                                 xhci_trb_ring_fini(trb_ring);
    597                                 free32(trb_ring);
    598                         }
    599                 }
    600         }
    601 
    602569        free32(hc->dcbaa);
    603         free32(hc->dcbaa_virt);
    604570}
    605571
     
    610576        xhci_event_ring_fini(&hc->event_ring);
    611577        hc_dcbaa_fini(hc);
    612         xhci_fini_transfers(hc);
    613578        xhci_fini_commands(hc);
    614579        xhci_rh_fini(&hc->rh);
  • uspace/drv/bus/usb/xhci/hc.h

    r766043c r2b61945  
    4646#include "bus.h"
    4747
    48 typedef struct xhci_virt_device_ctx {
    49         xhci_device_ctx_t *dev_ctx;
    50         xhci_trb_ring_t *trs[XHCI_EP_COUNT];
    51 } xhci_virt_device_ctx_t;
    52 
    5348typedef struct xhci_hc {
    5449        /* MMIO range */
     
    6863        xhci_event_ring_t event_ring;
    6964        uint64_t *dcbaa;
    70         xhci_virt_device_ctx_t *dcbaa_virt;
    7165        xhci_scratchpad_t *scratchpad;
    7266
     
    8478        list_t commands;
    8579        fibril_mutex_t commands_mtx;
    86 
    87         list_t transfers;
    8880
    8981        /* TODO: Hack. Figure out a better way. */
  • uspace/drv/bus/usb/xhci/hw_struct/trb.h

    r766043c r2b61945  
    100100#define TRB_CYCLE(trb)          XHCI_DWORD_EXTRACT((trb).control, 0, 0)
    101101#define TRB_LINK_TC(trb)        XHCI_DWORD_EXTRACT((trb).control, 1, 1)
     102#define TRB_IOC(trb)            XHCI_DWORD_EXTRACT((trb).control, 5, 5)
    102103
    103104#define TRB_TRANSFER_LENGTH(trb)        XHCI_DWORD_EXTRACT((trb).status, 23, 0)
  • uspace/drv/bus/usb/xhci/rh.c

    r766043c r2b61945  
    9292}
    9393
    94 // TODO: Check device deallocation, we free device_ctx in hc.c, not
    95 //       sure about the other structs.
    9694// TODO: This currently assumes the device is attached to rh directly.
    9795//       Also, we should consider moving a lot of functionailty to xhci bus
    9896int xhci_rh_address_device(xhci_rh_t *rh, device_t *dev, xhci_bus_t *bus)
    9997{
     98        int err;
     99        xhci_device_t *xhci_dev = xhci_device_get(dev);
     100
    100101        /* FIXME: Certainly not generic solution. */
    101102        const uint32_t route_str = 0;
    102103
    103         int err;
    104         xhci_hc_t *hc = rh->hc;
     104        xhci_dev->hc = rh->hc;
     105
    105106        const xhci_port_speed_t *speed = xhci_rh_get_port_speed(rh, dev->port);
     107        xhci_dev->usb3 = speed->major == 3;
    106108
    107109        /* Enable new slot */
    108         uint32_t slot_id;
    109         if ((err = hc_enable_slot(hc, &slot_id)) != EOK)
     110        if ((err = hc_enable_slot(rh->hc, &xhci_dev->slot_id)) != EOK)
    110111                return err;
    111         usb_log_debug2("Obtained slot ID: %u.\n", slot_id);
     112        usb_log_debug2("Obtained slot ID: %u.\n", xhci_dev->slot_id);
    112113
    113114        /* Setup input context */
    114         xhci_input_ctx_t *ictx = malloc(sizeof(xhci_input_ctx_t));
     115        xhci_input_ctx_t *ictx = malloc32(sizeof(xhci_input_ctx_t));
    115116        if (!ictx)
    116117                return ENOMEM;
     
    126127        XHCI_SLOT_ROUTE_STRING_SET(ictx->slot_ctx, route_str);
    127128
    128         xhci_trb_ring_t *ep_ring = malloc(sizeof(xhci_trb_ring_t));
    129         if (!ep_ring) {
    130                 err = ENOMEM;
     129        endpoint_t *ep0_base = bus_create_endpoint(&rh->hc->bus.base);
     130        if (!ep0_base)
    131131                goto err_ictx;
    132         }
    133 
    134         err = xhci_trb_ring_init(ep_ring);
    135         if (err)
    136                 goto err_ring;
    137         setup_control_ep0_ctx(&ictx->endpoint_ctx[0], ep_ring, speed);
     132        xhci_endpoint_t *ep0 = xhci_endpoint_get(ep0_base);
     133        setup_control_ep0_ctx(&ictx->endpoint_ctx[0], &ep0->ring, speed);
    138134
    139135        /* Setup and register device context */
     
    141137        if (!dctx) {
    142138                err = ENOMEM;
    143                 goto err_ring;
    144         }
     139                goto err_ep;
     140        }
     141        xhci_dev->dev_ctx = dctx;
     142        rh->hc->dcbaa[xhci_dev->slot_id] = addr_to_phys(dctx);
    145143        memset(dctx, 0, sizeof(xhci_device_ctx_t));
    146         hc->dcbaa[slot_id] = addr_to_phys(dctx);
    147 
    148         memset(&hc->dcbaa_virt[slot_id], 0, sizeof(xhci_virt_device_ctx_t));
    149         hc->dcbaa_virt[slot_id].dev_ctx = dctx;
    150         hc->dcbaa_virt[slot_id].trs[0] = ep_ring;
    151144
    152145        /* Address device */
    153         if ((err = hc_address_device(hc, slot_id, ictx)) != EOK)
     146        if ((err = hc_address_device(rh->hc, xhci_dev->slot_id, ictx)) != EOK)
    154147                goto err_dctx;
    155148        dev->address = XHCI_SLOT_DEVICE_ADDRESS(dctx->slot_ctx);
    156149        usb_log_debug2("Obtained USB address: %d.\n", dev->address);
    157150
    158         // Ask libusbhost to create a control endpoint for EP0.
    159         bus_t *bus_base = &bus->base;
    160         usb_target_t ep0_target = { .address = dev->address, .endpoint = 0 };
    161         usb_direction_t ep0_direction = USB_DIRECTION_BOTH;
    162 
    163         // TODO: Should this call be unified with other calls to `bus_add_ep()`?
    164         err = bus_add_ep(bus_base, dev, ep0_target.endpoint, ep0_direction,
    165             USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE, CTRL_PIPE_MIN_PACKET_SIZE, 1);
    166 
    167         if (err != EOK)
    168                 goto err_add_ep;
    169 
    170         // Save all data structures in the corresponding xhci_device_t.
    171         endpoint_t *ep0_base = bus_find_endpoint(bus_base, ep0_target, ep0_direction);
    172         xhci_endpoint_t *ep0 = xhci_endpoint_get(ep0_base);
    173         xhci_device_t *xhci_dev = ep0->device;
    174 
    175         xhci_dev->device = dev;
    176         xhci_dev->slot_id = slot_id;
    177         xhci_dev->usb3 = speed->major == 3;
    178         xhci_dev->hc = hc;
     151        // XXX: Going around bus, duplicating code
     152        ep0_base->device = dev;
     153        ep0_base->target.address = dev->address;
     154        ep0_base->target.endpoint = 0;
     155        ep0_base->direction = USB_DIRECTION_BOTH;
     156        ep0_base->transfer_type = USB_TRANSFER_CONTROL;
     157        ep0_base->max_packet_size = CTRL_PIPE_MIN_PACKET_SIZE;
     158        ep0_base->packets = 1;
     159        ep0_base->bandwidth = CTRL_PIPE_MIN_PACKET_SIZE;
     160
     161        bus_register_endpoint(&rh->hc->bus.base, ep0_base);
    179162
    180163        if (!rh->devices[dev->port - 1]) {
     
    183166        }
    184167
    185         return EOK;
    186 
    187 err_add_ep:
     168        free32(ictx);
     169        return EOK;
     170
    188171err_dctx:
    189         if (dctx) {
    190                 free(dctx);
    191                 hc->dcbaa[slot_id] = 0;
    192                 memset(&hc->dcbaa_virt[slot_id], 0, sizeof(xhci_virt_device_ctx_t));
    193         }
    194 err_ring:
    195         if (ep_ring) {
    196                 xhci_trb_ring_fini(ep_ring);
    197                 free(ep_ring);
    198         }
     172        free32(dctx);
     173        rh->hc->dcbaa[xhci_dev->slot_id] = 0;
     174err_ep:
     175        xhci_endpoint_fini(ep0);
     176        free(ep0);
    199177err_ictx:
    200         free(ictx);
     178        free32(ictx);
    201179        return err;
    202180}
  • uspace/drv/bus/usb/xhci/scratchpad.c

    r766043c r2b61945  
    132132
    133133        hc->dcbaa[0] = 0;
    134         memset(&hc->dcbaa_virt[0], 0, sizeof(xhci_virt_device_ctx_t));
    135134
    136135        return;
  • uspace/drv/bus/usb/xhci/transfers.c

    r766043c r2b61945  
    9494}
    9595
    96 int xhci_init_transfers(xhci_hc_t *hc)
    97 {
    98         assert(hc);
    99 
    100         list_initialize(&hc->transfers);
    101         return EOK;
    102 }
    103 
    104 void xhci_fini_transfers(xhci_hc_t *hc)
    105 {
    106         // Note: Untested.
    107         assert(hc);
    108 }
    109 
    110 xhci_transfer_t* xhci_transfer_create(endpoint_t* ep) {
    111         xhci_transfer_t* transfer = calloc(1, sizeof(xhci_transfer_t));
    112         if (!transfer)
    113                 return NULL;
     96/**
     97 * There can currently be only one active transfer, because
     98 * usb_transfer_batch_init locks the endpoint by endpoint_use.
     99 * Therefore, we store the only active transfer per endpoint there.
     100 */
     101xhci_transfer_t* xhci_transfer_create(endpoint_t* ep)
     102{
     103        xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep);
     104        xhci_transfer_t *transfer = &xhci_ep->active_transfer;
     105
     106        /* Do not access the transfer yet, it may be still in use. */
    114107
    115108        usb_transfer_batch_init(&transfer->batch, ep);
    116 
    117         link_initialize(&transfer->link);
     109        assert(ep->active);
     110
     111        /* Clean just our data. */
     112        memset(((void *) transfer) + sizeof(usb_transfer_batch_t), 0,
     113            sizeof(xhci_transfer_t) - sizeof(usb_transfer_batch_t));
    118114
    119115        return transfer;
     
    126122        if (transfer->hc_buffer)
    127123                free32(transfer->hc_buffer);
    128 
    129         free(transfer);
    130124}
    131125
    132126static xhci_trb_ring_t *get_ring(xhci_hc_t *hc, xhci_transfer_t *transfer)
    133127{
    134         xhci_endpoint_t *xhci_ep = xhci_endpoint_get(transfer->batch.ep);
    135         uint8_t slot_id = xhci_ep->device->slot_id;
    136 
    137         xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[transfer->batch.ep->target.endpoint];
    138         assert(ring);
    139         return ring;
     128        return &xhci_endpoint_get(transfer->batch.ep)->ring;
    140129}
    141130
     
    202191        // Issue a Configure Endpoint command, if needed.
    203192        if (configure_endpoint_needed(setup)) {
    204                 const int err = xhci_device_configure(xhci_ep->device, hc);
     193                const int err = xhci_device_configure(xhci_ep_to_dev(xhci_ep), hc);
    205194                if (err)
    206195                        return err;
     
    226215        TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
    227216
    228         xhci_endpoint_t *xhci_ep = xhci_endpoint_get(transfer->batch.ep);
    229         uint8_t slot_id = xhci_ep->device->slot_id;
    230         xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[transfer->batch.ep->target.endpoint];
     217        xhci_trb_ring_t* ring = get_ring(hc, transfer);
    231218
    232219        return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
     
    249236        TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
    250237
    251         xhci_endpoint_t *xhci_ep = xhci_endpoint_get(transfer->batch.ep);
    252         uint8_t slot_id = xhci_ep->device->slot_id;
    253         xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[transfer->batch.ep->target.endpoint];
     238        xhci_trb_ring_t* ring = get_ring(hc, transfer);
    254239
    255240        return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
     
    266251{
    267252        uintptr_t addr = trb->parameter;
    268         xhci_transfer_t *transfer = NULL;
    269 
    270         link_t *transfer_link = list_first(&hc->transfers);
    271         while (transfer_link) {
    272                 transfer = list_get_instance(transfer_link, xhci_transfer_t, link);
    273 
    274                 if (transfer->interrupt_trb_phys == addr)
    275                         break;
    276 
    277                 transfer_link = list_next(transfer_link, &hc->transfers);
    278         }
    279 
    280         if (!transfer_link) {
    281                 usb_log_warning("Transfer not found.");
     253        const unsigned slot_id = XHCI_DWORD_EXTRACT(trb->control, 31, 24);
     254        const unsigned ep_dci = XHCI_DWORD_EXTRACT(trb->control, 20, 16);
     255
     256        xhci_device_t *dev = hc->bus.devices_by_slot[slot_id];
     257        if (!dev) {
     258                usb_log_error("Transfer event on unknown device slot %u!", slot_id);
    282259                return ENOENT;
    283260        }
    284261
    285         list_remove(transfer_link);
     262        const usb_endpoint_t ep_num = ep_dci / 2;
     263        xhci_endpoint_t *ep = xhci_device_get_endpoint(dev, ep_num);
     264        if (!ep) {
     265                usb_log_error("Transfer event on unknown endpoint num %u, device slot %u!", ep_num, slot_id);
     266                return ENOENT;
     267        }
     268
     269        xhci_transfer_t *transfer = &ep->active_transfer;
     270
     271        /** FIXME: This is racy. Do we care? */
     272        ep->ring.dequeue = addr;
     273
    286274        usb_transfer_batch_t *batch = &transfer->batch;
    287275
     
    314302        xhci_transfer_t *transfer = xhci_transfer_from_batch(batch);
    315303        xhci_endpoint_t *xhci_ep = xhci_endpoint_get(batch->ep);
    316         uint8_t slot_id = xhci_ep->device->slot_id;
    317 
    318304        assert(xhci_ep);
    319         assert(slot_id);
    320305
    321306        const usb_transfer_type_t type = batch->ep->transfer_type;
     
    336321                return err;
    337322
    338         list_append(&transfer->link, &hc->transfers);
    339 
     323        const uint8_t slot_id = xhci_ep_to_dev(xhci_ep)->slot_id;
    340324        const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */
    341325        return hc_ring_doorbell(hc, slot_id, target);
  • uspace/drv/bus/usb/xhci/transfers.h

    r766043c r2b61945  
    5454} xhci_transfer_t;
    5555
    56 int xhci_init_transfers(xhci_hc_t*);
    57 void xhci_fini_transfers(xhci_hc_t*);
    58 
    5956xhci_transfer_t* xhci_transfer_create(endpoint_t *);
    6057int xhci_transfer_schedule(xhci_hc_t*, usb_transfer_batch_t *);
  • uspace/drv/bus/usb/xhci/trb_ring.c

    r766043c r2b61945  
    155155}
    156156
     157static bool trb_generates_interrupt(xhci_trb_t *trb)
     158{
     159        return TRB_TYPE(*trb) >= XHCI_TRB_TYPE_ENABLE_SLOT_CMD
     160                || TRB_IOC(*trb);
     161}
     162
    157163/**
    158164 * Enqueue TDs composed of TRBs.
     
    188194        xhci_trb_t *trb = first_trb;
    189195        for (size_t i = 0; i < trbs; ++i, ++trb) {
     196                if (trb_generates_interrupt(trb)) {
     197                        if (*phys)
     198                                return ENOTSUP;
     199                        *phys = trb_ring_enqueue_phys(ring);
     200                }
     201
    190202                ring->enqueue_trb++;
    191203
     
    205217        trb = first_trb;
    206218        for (size_t i = 0; i < trbs; ++i, ++trb) {
    207                 if (phys && i == trbs - 1)
    208                         *phys = trb_ring_enqueue_phys(ring);
    209 
    210219                xhci_trb_set_cycle(trb, ring->pcs);
    211220                xhci_trb_copy(ring->enqueue_trb, trb);
  • uspace/lib/usbhost/src/hcd.c

    r766043c r2b61945  
    4141#include <errno.h>
    4242#include <usb_iface.h>
     43#include <str_error.h>
    4344
    4445#include "hcd.h"
     
    128129
    129130        const int ret = hcd->ops.schedule(hcd, batch);
    130         if (ret != EOK)
     131        if (ret != EOK) {
     132                usb_log_warning("Batch %p failed to schedule: %s", batch, str_error(ret));
    131133                usb_transfer_batch_destroy(batch);
     134        }
    132135
    133136        /* Drop our own reference to ep. */
  • uspace/lib/usbhost/src/usb_transfer_batch.c

    r766043c r2b61945  
    4040#include <assert.h>
    4141#include <errno.h>
     42#include <str_error.h>
    4243
    4344
     
    6263void usb_transfer_batch_init(usb_transfer_batch_t *batch, endpoint_t *ep)
    6364{
     65        endpoint_use(ep);
     66
    6467        memset(batch, 0, sizeof(*batch));
    65 
    6668        batch->ep = ep;
    67 
    68         endpoint_use(ep);
    6969}
    7070
     
    103103        assert(batch->ep->bus);
    104104
    105         usb_log_debug2("batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n",
    106             batch, USB_TRANSFER_BATCH_ARGS(*batch));
    107 
    108105        bus_t *bus = batch->ep->bus;
    109         if (bus->ops.destroy_batch)
     106        if (bus->ops.destroy_batch) {
     107                usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " destroying.\n",
     108                    batch, USB_TRANSFER_BATCH_ARGS(*batch));
    110109                bus->ops.destroy_batch(batch);
    111         else
     110        }
     111        else {
     112                usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n",
     113                    batch, USB_TRANSFER_BATCH_ARGS(*batch));
    112114                free(batch);
     115        }
    113116
    114117        endpoint_release(batch->ep);
     
    123126void usb_transfer_batch_finish(usb_transfer_batch_t *batch)
    124127{
    125         if (!batch_complete(batch))
    126                 usb_log_warning("failed to complete batch %p!", batch);
     128        const int err = batch_complete(batch);
     129        if (err)
     130                usb_log_warning("batch %p failed to complete: %s", batch, str_error(err));
    127131
    128132        usb_transfer_batch_destroy(batch);
     
    159163        struct old_handler_wrapper_data *data = malloc(sizeof(*data));
    160164
     165        assert((!in_callback) != (!out_callback));
     166
    161167        data->in_callback = in_callback;
    162168        data->out_callback = out_callback;
Note: See TracChangeset for help on using the changeset viewer.