Index: uspace/drv/bus/usb/xhci/bus.c
===================================================================
--- uspace/drv/bus/usb/xhci/bus.c	(revision 5fd9c308725be28e98aaeb91d9f3367e470de4f1)
+++ uspace/drv/bus/usb/xhci/bus.c	(revision 2e5aea1793c59721de23e0320a1e7f8f2aebc260)
@@ -35,4 +35,5 @@
 #include <adt/hash_table.h>
 #include <adt/hash.h>
+#include <usb/host/utils/malloc32.h>
 #include <usb/host/ddf_helpers.h>
 #include <usb/host/endpoint.h>
@@ -58,4 +59,8 @@
 } hashed_device_t;
 
+static int hashed_device_insert(xhci_bus_t *bus, hashed_device_t **hashed_dev, xhci_device_t *dev);
+static int hashed_device_remove(xhci_bus_t *bus, hashed_device_t *hashed_dev);
+static int hashed_device_find_by_address(xhci_bus_t *bus, usb_address_t address, hashed_device_t **dev);
+
 /** TODO: Still some copy-pasta left...
  */
@@ -63,4 +68,5 @@
 {
 	int err;
+	xhci_device_t *xhci_dev = xhci_device_get(dev);
 
 	/* TODO: get speed from the default address reservation */
@@ -85,17 +91,45 @@
 	}
 
+	assert(bus->devices_by_slot[xhci_dev->slot_id] == NULL);
+	bus->devices_by_slot[xhci_dev->slot_id] = xhci_dev;
+
+	hashed_device_t *hashed_dev = NULL;
+	if ((err = hashed_device_insert(bus, &hashed_dev, xhci_dev)))
+		goto err_address;
+
 	/* Read the device descriptor, derive the match ids */
 	if ((err = hcd_ddf_device_explore(hc->hcd, dev))) {
 		usb_log_error("Device(%d): Failed to explore device: %s", dev->address, str_error(err));
-		bus_release_address(&bus->base, dev->address);
-		return err;
-	}
-
-	return EOK;
+		goto err_hash;
+	}
+
+	return EOK;
+
+err_hash:
+	bus->devices_by_slot[xhci_dev->slot_id] = NULL;
+	hashed_device_remove(bus, hashed_dev);
+err_address:
+	bus_release_address(&bus->base, dev->address);
+	return err;
 }
 
 int xhci_bus_remove_device(xhci_bus_t *bus, xhci_hc_t *hc, device_t *dev)
 {
-	// TODO: Implement me!
+	xhci_device_t *xhci_dev = xhci_device_get(dev);
+
+	// TODO: Release remaining EPs
+
+	hashed_device_t *hashed_dev;
+	int res = hashed_device_find_by_address(bus, dev->address, &hashed_dev);
+	if (res)
+		return res;
+
+	res = hashed_device_remove(bus, hashed_dev);
+	if (res != EOK)
+		return res;
+
+	// XXX: Ugly here. Move to device_destroy at endpoint.c?
+	free32(xhci_dev->dev_ctx);
+	hc->dcbaa[xhci_dev->slot_id] = 0;
 	return ENOTSUP;
 }
@@ -134,5 +168,5 @@
 	xhci_bus_t *bus = bus_to_xhci_bus(base);
 
-	xhci_endpoint_t *ep = malloc(sizeof(xhci_endpoint_t));
+	xhci_endpoint_t *ep = calloc(1, sizeof(xhci_endpoint_t));
 	if (!ep)
 		return NULL;
@@ -179,46 +213,24 @@
 }
 
-static int hashed_device_create(xhci_bus_t *bus, hashed_device_t **hashed_dev, usb_address_t address)
-{
-	int res;
-	xhci_device_t *dev = (xhci_device_t *) malloc(sizeof(xhci_device_t));
-	if (!dev) {
-		res = ENOMEM;
-		goto err_xhci_dev_alloc;
-	}
-
-	res = xhci_device_init(dev, bus, address);
-	if (res != EOK) {
-		goto err_xhci_dev_init;
-	}
-
-	hashed_device_t *ret_dev = (hashed_device_t *) malloc(sizeof(hashed_device_t));
-	if (!ret_dev) {
-		res = ENOMEM;
-		goto err_hashed_dev_alloc;
-	}
+static int hashed_device_insert(xhci_bus_t *bus, hashed_device_t **hashed_dev, xhci_device_t *dev)
+{
+	hashed_device_t *ret_dev = (hashed_device_t *) calloc(1, sizeof(hashed_device_t));
+	if (!ret_dev)
+		return ENOMEM;
 
 	ret_dev->device = dev;
 
-	usb_log_info("Device(%d) registered to XHCI bus.", dev->address);
+	usb_log_info("Device(%d) registered to XHCI bus.", dev->base.address);
 
 	hash_table_insert(&bus->devices, &ret_dev->link);
 	*hashed_dev = ret_dev;
 	return EOK;
-
-err_hashed_dev_alloc:
-err_xhci_dev_init:
-	free(dev);
-err_xhci_dev_alloc:
-	return res;
 }
 
 static int hashed_device_remove(xhci_bus_t *bus, hashed_device_t *hashed_dev)
 {
-	usb_log_info("Device(%d) released from XHCI bus.", hashed_dev->device->address);
-
-	hash_table_remove(&bus->devices, &hashed_dev->device->address);
-	xhci_device_fini(hashed_dev->device);
-	free(hashed_dev->device);
+	usb_log_info("Device(%d) released from XHCI bus.", hashed_dev->device->base.address);
+
+	hash_table_remove(&bus->devices, &hashed_dev->device->base.address);
 	free(hashed_dev);
 
@@ -231,19 +243,9 @@
 	assert(bus);
 
-	hashed_device_t *hashed_dev;
-	int res = hashed_device_find_by_address(bus, ep->target.address, &hashed_dev);
-	if (res != EOK && res != ENOENT)
-		return res;
-
-	if (res == ENOENT) {
-		res = hashed_device_create(bus, &hashed_dev, ep->target.address);
-
-		if (res != EOK)
-			return res;
-	}
-
 	usb_log_info("Endpoint(%d:%d) registered to XHCI bus.", ep->target.address, ep->target.endpoint);
 
-	return xhci_device_add_endpoint(hashed_dev->device, xhci_endpoint_get(ep));
+	xhci_device_t *xhci_dev = xhci_device_get(ep->device);
+	xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep);
+	return xhci_device_add_endpoint(xhci_dev, xhci_ep);
 }
 
@@ -255,20 +257,10 @@
 	usb_log_info("Endpoint(%d:%d) released from XHCI bus.", ep->target.address, ep->target.endpoint);
 
-	hashed_device_t *hashed_dev;
-	int res = hashed_device_find_by_address(bus, ep->target.address, &hashed_dev);
+	xhci_device_t *xhci_dev = xhci_device_get(ep->device);
+	xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep);
+	const int res = xhci_device_remove_endpoint(xhci_dev, xhci_ep);
 	if (res != EOK)
 		return res;
 
-	res = xhci_device_remove_endpoint(hashed_dev->device, xhci_endpoint_get(ep));
-	if (res != EOK)
-		return res;
-
-	if (hashed_dev->device->active_endpoint_count == 0) {
-		res = hashed_device_remove(bus, hashed_dev);
-
-		if (res != EOK)
-			return res;
-	}
-
 	return EOK;
 }
@@ -278,5 +270,5 @@
 	xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
 	assert(bus);
-
+	
 	xhci_endpoint_t *ep;
 	int res = xhci_endpoint_find_by_target(bus, target, &ep);
@@ -349,5 +341,5 @@
 {
 	hashed_device_t *dev = hash_table_get_inst(item, hashed_device_t, link);
-	return (size_t) hash_mix(dev->device->address);
+	return (size_t) hash_mix(dev->device->base.address);
 }
 
@@ -360,5 +352,5 @@
 {
 	hashed_device_t *dev = hash_table_get_inst(item, hashed_device_t, link);
-	return dev->device->address == *(usb_address_t *) key;
+	return dev->device->base.address == *(usb_address_t *) key;
 }
 
@@ -372,12 +364,16 @@
 };
 
-int xhci_bus_init(xhci_bus_t *bus)
-{
-	assert(bus);
-
-	bus_init(&bus->base, sizeof(device_t));
+int xhci_bus_init(xhci_bus_t *bus, xhci_hc_t *hc)
+{
+	assert(bus);
+
+	bus_init(&bus->base, sizeof(xhci_device_t));
+
+	bus->devices_by_slot = calloc(hc->max_slots, sizeof(xhci_device_t *));
+	if (!bus->devices_by_slot)
+		return ENOMEM;
 
 	if (!hash_table_create(&bus->devices, 0, 0, &device_ht_ops)) {
-		// FIXME: Dealloc base!
+		free(bus->devices_by_slot);
 		return ENOMEM;
 	}
