Index: uspace/drv/ohci/ohci.c
===================================================================
--- uspace/drv/ohci/ohci.c	(revision 62265ce4a17948e39e68b43102deba3223a20599)
+++ uspace/drv/ohci/ohci.c	(revision dc5f2fb8272d054c65a8b9eb4e713a8c923f8b07)
@@ -44,4 +44,21 @@
 #include "iface.h"
 #include "pci.h"
+#include "hc.h"
+#include "root_hub.h"
+
+typedef struct ohci {
+	ddf_fun_t *hc_fun;
+	ddf_fun_t *rh_fun;
+
+	hc_t hc;
+	rh_t rh;
+} ohci_t;
+
+static inline ohci_t * dev_to_ohci(ddf_dev_t *dev)
+{
+	assert(dev);
+	assert(dev->driver_data);
+	return dev->driver_data;
+}
 
 /** IRQ handling callback, identifies device
@@ -53,9 +70,7 @@
 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
 {
-	assert(dev);
-	assert(dev->driver_data);
-	hc_t *hc = &((ohci_t*)dev->driver_data)->hc;
-	uint16_t status = IPC_GET_ARG1(*call);
+	hc_t *hc = &dev_to_ohci(dev)->hc;
 	assert(hc);
+	const uint16_t status = IPC_GET_ARG1(*call);
 	hc_interrupt(hc, status);
 }
@@ -71,5 +86,5 @@
 {
 	assert(fun);
-	usb_device_keeper_t *manager = &((ohci_t*)fun->dev->driver_data)->hc.manager;
+	usb_device_keeper_t *manager = &dev_to_ohci(fun->dev)->hc.manager;
 
 	usb_address_t addr = usb_device_keeper_find(manager, handle);
@@ -95,6 +110,7 @@
 {
 	assert(handle);
-	ddf_fun_t *hc_fun = ((ohci_t*)fun->dev->driver_data)->hc_fun;
-	assert(hc_fun != NULL);
+	assert(fun);
+	ddf_fun_t *hc_fun = dev_to_ohci(fun->dev)->hc_fun;
+	assert(hc_fun);
 
 	*handle = hc_fun->handle;
@@ -102,5 +118,5 @@
 }
 /*----------------------------------------------------------------------------*/
-/** This iface is generic for both RH and HC. */
+/** Root hub USB interface */
 static usb_iface_t usb_iface = {
 	.get_hc_handle = usb_iface_get_hc_handle,
@@ -108,8 +124,10 @@
 };
 /*----------------------------------------------------------------------------*/
+/** Standard USB HC options (HC interface) */
 static ddf_dev_ops_t hc_ops = {
 	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
 };
 /*----------------------------------------------------------------------------*/
+/** Standard USB RH options (RH interface) */
 static ddf_dev_ops_t rh_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface,
@@ -118,6 +136,6 @@
 /** Initialize hc and rh ddf structures and their respective drivers.
  *
+ * @param[in] device DDF instance of the device to use.
  * @param[in] instance OHCI structure to use.
- * @param[in] device DDF instance of the device to use.
  *
  * This function does all the preparatory work for hc and rh drivers:
@@ -127,48 +145,50 @@
  *  - registers interrupt handler
  */
-int device_setup_ohci(ddf_dev_t *device, ohci_t *instance)
-{
-	assert(instance);
+int device_setup_ohci(ddf_dev_t *device)
+{
+	ohci_t *instance = malloc(sizeof(ohci_t));
+	if (instance == NULL) {
+		usb_log_error("Failed to allocate OHCI driver.\n");
+		return ENOMEM;
+	}
+
+#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
+if (ret != EOK) { \
+	if (instance->hc_fun) { \
+		instance->hc_fun->ops = NULL; \
+		instance->hc_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->hc_fun); \
+	} \
+	if (instance->rh_fun) { \
+		instance->rh_fun->ops = NULL; \
+		instance->rh_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->rh_fun); \
+	} \
+	free(instance); \
+	usb_log_error(message); \
+	return ret; \
+} else (void)0
 
 	instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci-hc");
-	if (instance->hc_fun == NULL) {
-		usb_log_error("Failed to create HC function.\n");
-		return ENOMEM;
-	}
+	int ret = instance->hc_fun ? EOK : ENOMEM;
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI HC function.\n");
 	instance->hc_fun->ops = &hc_ops;
 	instance->hc_fun->driver_data = &instance->hc;
 
 	instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci-rh");
-	if (instance->rh_fun == NULL) {
-		ddf_fun_destroy(instance->hc_fun);
-		usb_log_error("Failed to create RH function.\n");
-		return ENOMEM;
-	}
+	ret = instance->rh_fun ? EOK : ENOMEM;
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI RH function.\n");
 	instance->rh_fun->ops = &rh_ops;
-	instance->rh_fun->driver_data = NULL;
-
-#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
-if (ret != EOK) { \
-	usb_log_error(message); \
-	instance->hc_fun->ops = NULL; \
-	instance->hc_fun->driver_data = NULL; \
-	instance->rh_fun->ops = NULL; \
-	instance->rh_fun->driver_data = NULL; \
-	ddf_fun_destroy(instance->hc_fun); \
-	ddf_fun_destroy(instance->rh_fun); \
-	return ret; \
-}
-
-	uintptr_t mem_reg_base = 0;
-	size_t mem_reg_size = 0;
+
+	uintptr_t reg_base = 0;
+	size_t reg_size = 0;
 	int irq = 0;
 
-	int ret =
-	    pci_get_my_registers(device, &mem_reg_base, &mem_reg_size, &irq);
-	CHECK_RET_DEST_FUN_RETURN(ret,
+	ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
+	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed to get memory addresses for %" PRIun ": %s.\n",
 	    device->handle, str_error(ret));
 	usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
-	    (void *) mem_reg_base, mem_reg_size, irq);
+	    (void *) reg_base, reg_size, irq);
 
 	bool interrupts = false;
@@ -189,12 +209,12 @@
 #endif
 
-	ret = hc_init(&instance->hc, mem_reg_base, mem_reg_size, interrupts);
-	CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init ohci-hcd.\n", ret);
+	ret = hc_init(&instance->hc, reg_base, reg_size, interrupts);
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed(%d) to init ohci-hcd.\n", ret);
 
 #define CHECK_RET_FINI_RETURN(ret, message...) \
 if (ret != EOK) { \
 	hc_fini(&instance->hc); \
-	CHECK_RET_DEST_FUN_RETURN(ret, message); \
-}
+	CHECK_RET_DEST_FREE_RETURN(ret, message); \
+} else (void)0
 
 	/* It does no harm if we register this on polling */
@@ -212,4 +232,5 @@
 
 	hc_start_hw(&instance->hc);
+	hc_register_hub(&instance->hc, instance->rh_fun);
 	return EOK;
 
