Changeset c10daa8 in mainline for uspace/drv/bus/usb/xhci/bus.c


Ignore:
Timestamp:
2017-10-13T12:32:57Z (7 years ago)
Author:
Petr Manek <petr.manek@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
063dfe8
Parents:
366e9b6
Message:

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

File:
1 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/**
Note: See TracChangeset for help on using the changeset viewer.