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

Changeset c10daa8 in mainline


Ignore:
Timestamp:
2017-10-13T12:32:57Z (3 years ago)
Author:
Petr Manek <petr.manek@…>
Branches:
master
Children:
063dfe8
Parents:
366e9b6
Message:

Refactored XHCI bus to hold devices instead of endpoints. Added middle layer to keep track of endpoints within devices.

Location:
uspace/drv/bus/usb/xhci
Files:
5 edited

Legend:

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

    r366e9b6 rc10daa8  
    5050        ht_link_t link;
    5151
    52         /** Endpoint */
    53         xhci_endpoint_t *endpoint;
    54 } hashed_endpoint_t;
     52        /** Device */
     53        xhci_device_t *device;
     54} hashed_device_t;
    5555
    5656/** Ops receive generic bus_t pointer. */
     
    8585}
    8686
    87 static int endpoint_find_by_target(xhci_bus_t *bus, usb_target_t target, hashed_endpoint_t **ep)
    88 {
    89         ht_link_t *link = hash_table_find(&bus->endpoints, &target.packed);
     87static int hashed_device_find_by_address(xhci_bus_t *bus, usb_address_t address, hashed_device_t **dev)
     88{
     89        ht_link_t *link = hash_table_find(&bus->devices, &address);
    9090        if (link == NULL)
    9191                return ENOENT;
    9292
    93         *ep = hash_table_get_inst(link, hashed_endpoint_t, link);
    94         return EOK;
    95 }
    96 
    97 static int register_endpoint(bus_t *bus_base, endpoint_t *ep)
    98 {
    99         xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
    100         assert(bus);
    101 
    102         hashed_endpoint_t *hashed_ep =
    103             (hashed_endpoint_t *) malloc(sizeof(hashed_endpoint_t));
    104         if (!hashed_ep)
    105                 return ENOMEM;
    106 
    107         hashed_ep->endpoint = xhci_endpoint_get(ep);
    108         hash_table_insert(&bus->endpoints, &hashed_ep->link);
    109 
    110         return EOK;
    111 }
    112 
    113 static int release_endpoint(bus_t *bus_base, endpoint_t *ep)
    114 {
    115         xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
    116         assert(bus);
    117 
    118         hashed_endpoint_t *hashed_ep;
    119         int res = endpoint_find_by_target(bus, ep->target, &hashed_ep);
     93        *dev = hash_table_get_inst(link, hashed_device_t, link);
     94        return EOK;
     95}
     96
     97static int xhci_endpoint_find_by_target(xhci_bus_t *bus, usb_target_t target, xhci_endpoint_t **ep)
     98{
     99        hashed_device_t *dev;
     100        int res = hashed_device_find_by_address(bus, target.address, &dev);
    120101        if (res != EOK)
    121102                return res;
    122103
    123         hash_table_remove(&bus->endpoints, &ep->target.packed);
    124         free(hashed_ep);
     104        xhci_endpoint_t *ret_ep = xhci_device_get_endpoint(dev->device, target.endpoint);
     105        if (!ret_ep)
     106                return ENOENT;
     107
     108        *ep = ret_ep;
     109        return EOK;
     110}
     111
     112static int hashed_device_create(xhci_bus_t *bus, hashed_device_t **hashed_dev)
     113{
     114        int res;
     115        xhci_device_t *dev = (xhci_device_t *) malloc(sizeof(xhci_device_t));
     116        if (!dev) {
     117                res = ENOMEM;
     118                goto err_xhci_dev_alloc;
     119        }
     120
     121        res = xhci_device_init(dev, bus);
     122        if (res != EOK) {
     123                goto err_xhci_dev_init;
     124        }
     125
     126        // TODO: Set device data.
     127
     128        hashed_device_t *ret_dev = (hashed_device_t *) malloc(sizeof(hashed_device_t));
     129        if (!ret_dev) {
     130                res = ENOMEM;
     131                goto err_hashed_dev_alloc;
     132        }
     133
     134        ret_dev->device = dev;
     135
     136        hash_table_insert(&bus->devices, &ret_dev->link);
     137        *hashed_dev = ret_dev;
     138        return EOK;
     139
     140err_hashed_dev_alloc:
     141err_xhci_dev_init:
     142        free(dev);
     143err_xhci_dev_alloc:
     144        return res;
     145}
     146
     147static int hashed_device_remove(xhci_bus_t *bus, hashed_device_t *hashed_dev)
     148{
     149        hash_table_remove(&bus->devices, &hashed_dev->device->address);
     150        xhci_device_fini(hashed_dev->device);
     151        free(hashed_dev->device);
     152        free(hashed_dev);
     153
     154        return EOK;
     155}
     156
     157static int register_endpoint(bus_t *bus_base, endpoint_t *ep)
     158{
     159        xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
     160        assert(bus);
     161
     162        hashed_device_t *hashed_dev;
     163        int res = hashed_device_find_by_address(bus, ep->target.address, &hashed_dev);
     164        if (res != EOK && res != ENOENT)
     165                return res;
     166
     167        if (res == ENOENT) {
     168                res = hashed_device_create(bus, &hashed_dev);
     169
     170                if (res != EOK)
     171                        return res;
     172        }
     173
     174        return xhci_device_add_endpoint(hashed_dev->device, xhci_endpoint_get(ep));
     175}
     176
     177static int release_endpoint(bus_t *bus_base, endpoint_t *ep)
     178{
     179        xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
     180        assert(bus);
     181
     182        hashed_device_t *hashed_dev;
     183        int res = hashed_device_find_by_address(bus, ep->target.address, &hashed_dev);
     184        if (res != EOK)
     185                return res;
     186
     187        xhci_device_remove_endpoint(hashed_dev->device, xhci_endpoint_get(ep));
     188
     189        if (hashed_dev->device->active_endpoint_count == 0) {
     190                res = hashed_device_remove(bus, hashed_dev);
     191
     192                if (res != EOK)
     193                        return res;
     194        }
    125195
    126196        return EOK;
     
    132202        assert(bus);
    133203
    134         hashed_endpoint_t *hashed_ep;
    135         int res = endpoint_find_by_target(bus, target, &hashed_ep);
     204        xhci_endpoint_t *ep;
     205        int res = xhci_endpoint_find_by_target(bus, target, &ep);
    136206        if (res != EOK)
    137207                return NULL;
    138208
    139         return &hashed_ep->endpoint->base;
     209        return &ep->base;
    140210}
    141211
     
    205275};
    206276
    207 static size_t endpoint_ht_hash(const ht_link_t *item)
    208 {
    209         hashed_endpoint_t *ep = hash_table_get_inst(item, hashed_endpoint_t, link);
    210         return (size_t) hash_mix32(ep->endpoint->base.target.packed);
    211 }
    212 
    213 static size_t endpoint_ht_key_hash(void *key)
    214 {
    215         return (size_t) hash_mix32(*(uint32_t *)key);
    216 }
    217 
    218 static bool endpoint_ht_key_equal(void *key, const ht_link_t *item)
    219 {
    220         hashed_endpoint_t *ep = hash_table_get_inst(item, hashed_endpoint_t, link);
    221         return ep->endpoint->base.target.packed == *(uint32_t *) key;
    222 }
    223 
    224 /** Operations for the endpoint hash table. */
    225 static hash_table_ops_t endpoint_ht_ops = {
    226         .hash = endpoint_ht_hash,
    227         .key_hash = endpoint_ht_key_hash,
    228         .key_equal = endpoint_ht_key_equal,
     277static size_t device_ht_hash(const ht_link_t *item)
     278{
     279        hashed_device_t *dev = hash_table_get_inst(item, hashed_device_t, link);
     280        return (size_t) hash_mix(dev->device->address);
     281}
     282
     283static size_t device_ht_key_hash(void *key)
     284{
     285        return (size_t) hash_mix(*(usb_address_t *)key);
     286}
     287
     288static bool device_ht_key_equal(void *key, const ht_link_t *item)
     289{
     290        hashed_device_t *dev = hash_table_get_inst(item, hashed_device_t, link);
     291        return dev->device->address == *(usb_address_t *) key;
     292}
     293
     294/** Operations for the device hash table. */
     295static hash_table_ops_t device_ht_ops = {
     296        .hash = device_ht_hash,
     297        .key_hash = device_ht_key_hash,
     298        .key_equal = device_ht_key_equal,
    229299        .equal = NULL,
    230300        .remove_callback = NULL
     
    237307        bus_init(&bus->base);
    238308
    239         if (!hash_table_create(&bus->endpoints, 0, 0, &endpoint_ht_ops)) {
     309        if (!hash_table_create(&bus->devices, 0, 0, &device_ht_ops)) {
    240310                // FIXME: Dealloc base!
    241311                return ENOMEM;
     
    248318void xhci_bus_fini(xhci_bus_t *bus)
    249319{
    250         hash_table_destroy(&bus->endpoints);
     320        // FIXME: Make sure no devices are in the hash table.
     321
     322        hash_table_destroy(&bus->devices);
    251323}
    252324/**
  • uspace/drv/bus/usb/xhci/bus.h

    r366e9b6 rc10daa8  
    5252         */
    5353
    54         hash_table_t endpoints;
     54        hash_table_t devices;
    5555} xhci_bus_t;
    5656
  • uspace/drv/bus/usb/xhci/endpoint.c

    r366e9b6 rc10daa8  
    5050
    5151        endpoint_init(ep, bus);
    52 
    53         /* FIXME: Set xhci_ep->slot_id */
     52        xhci_ep->device = NULL;
    5453
    5554        usb_log_debug("XHCI Endpoint %d:%d initialized.", ep->target.address, ep->target.endpoint);
     
    6968}
    7069
     70int xhci_device_init(xhci_device_t *dev, xhci_bus_t *bus)
     71{
     72        memset(&dev->endpoints, 0, sizeof(dev->endpoints));
     73        dev->active_endpoint_count = 0;
     74        return EOK;
     75}
     76
     77void xhci_device_fini(xhci_device_t *dev)
     78{
     79        // TODO: Check that all endpoints are dead.
     80}
     81
     82int xhci_device_add_endpoint(xhci_device_t *dev, xhci_endpoint_t *ep)
     83{
     84        assert(dev->address == ep->base.target.address);
     85        assert(!dev->endpoints[ep->base.target.endpoint]);
     86        assert(!ep->device);
     87
     88        ep->device = dev;
     89        dev->endpoints[ep->base.target.endpoint] = ep;
     90        ++dev->active_endpoint_count;
     91        return EOK;
     92}
     93
     94int xhci_device_remove_endpoint(xhci_device_t *dev, xhci_endpoint_t *ep)
     95{
     96        assert(dev->address == ep->base.target.address);
     97        assert(dev->endpoints[ep->base.target.endpoint]);
     98        assert(dev == ep->device);
     99
     100        ep->device = NULL;
     101        dev->endpoints[ep->base.target.endpoint] = NULL;
     102        --dev->active_endpoint_count;
     103        return EOK;
     104}
     105
     106xhci_endpoint_t * xhci_device_get_endpoint(xhci_device_t *dev, usb_endpoint_t ep)
     107{
     108        return dev->endpoints[ep];
     109}
     110
    71111/**
    72112 * @}
  • uspace/drv/bus/usb/xhci/endpoint.h

    r366e9b6 rc10daa8  
    4343#include <usb/host/hcd.h>
    4444
     45typedef struct xhci_device xhci_device_t;
    4546typedef struct xhci_endpoint xhci_endpoint_t;
    4647typedef struct xhci_bus xhci_bus_t;
     48
     49#define XHCI_DEVICE_MAX_ENDPOINTS 32
    4750
    4851enum {
     
    6164        endpoint_t base;        /**< Inheritance. Keep this first. */
    6265
     66        xhci_device_t *device;
     67} xhci_endpoint_t;
     68
     69typedef struct xhci_device {
     70        usb_address_t address;
     71
    6372        uint32_t slot_id;
    64 } xhci_endpoint_t;
     73
     74        xhci_endpoint_t *endpoints[XHCI_DEVICE_MAX_ENDPOINTS];
     75        uint8_t active_endpoint_count;
     76} xhci_device_t;
    6577
    6678int xhci_endpoint_init(xhci_endpoint_t *, xhci_bus_t *);
    6779void xhci_endpoint_fini(xhci_endpoint_t *);
     80
     81int xhci_device_init(xhci_device_t *, xhci_bus_t *);
     82void xhci_device_fini(xhci_device_t *);
     83
     84int xhci_device_add_endpoint(xhci_device_t *, xhci_endpoint_t *);
     85int xhci_device_remove_endpoint(xhci_device_t *, xhci_endpoint_t *);
     86xhci_endpoint_t * xhci_device_get_endpoint(xhci_device_t *, usb_endpoint_t);
    6887
    6988static inline xhci_endpoint_t * xhci_endpoint_get(endpoint_t *ep)
  • uspace/drv/bus/usb/xhci/transfers.c

    r366e9b6 rc10daa8  
    150150        xhci_endpoint_t *xhci_ep = xhci_endpoint_get(batch->ep);
    151151
    152         uint8_t slot_id = xhci_ep->slot_id;
     152        uint8_t slot_id = xhci_ep->device->slot_id;
    153153        xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[0];
    154154
     
    234234
    235235        xhci_endpoint_t *xhci_ep = xhci_endpoint_get(batch->ep);
    236         uint8_t slot_id = xhci_ep->slot_id;
     236        uint8_t slot_id = xhci_ep->device->slot_id;
    237237        xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[batch->ep->target.endpoint];
    238238
Note: See TracChangeset for help on using the changeset viewer.