Index: .bzrignore
===================================================================
--- .bzrignore	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ .bzrignore	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -84,5 +84,6 @@
 ./uspace/drv/test1/test1
 ./uspace/drv/test2/test2
-./uspace/drv/uhci/uhci
+./uspace/drv/uhci-hcd/uhci-hcd
+./uspace/drv/uhci-rhd/uhci-rhd
 ./uspace/drv/usbhub/usbhub
 ./uspace/drv/usbhid/usbhid
Index: boot/arch/amd64/Makefile.inc
===================================================================
--- boot/arch/amd64/Makefile.inc	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ boot/arch/amd64/Makefile.inc	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -43,5 +43,6 @@
 	isa \
 	ns8250 \
-	uhci \
+	uhci-hcd \
+	uhci-rhd \
 	usbhub \
 	usbhid \
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ uspace/Makefile	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -117,5 +117,6 @@
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259 \
-		drv/uhci \
+		drv/uhci-hcd \
+		drv/uhci-rhd \
 		drv/usbhid \
 		drv/usbhub \
@@ -131,5 +132,6 @@
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259 \
-		drv/uhci \
+		drv/uhci-hcd \
+		drv/uhci-rhd \
 		drv/usbhid \
 		drv/usbhub \
Index: uspace/app/bdsh/cmds/modules/cat/cat.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cat/cat.c	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ uspace/app/bdsh/cmds/modules/cat/cat.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -144,14 +144,14 @@
 			return CMD_SUCCESS;
 		case 'H':
-			printf(cat_oops);
+			printf("%s", cat_oops);
 			return CMD_FAILURE;
 		case 't':
-			printf(cat_oops);
+			printf("%s", cat_oops);
 			return CMD_FAILURE;
 		case 'b':
-			printf(cat_oops);
+			printf("%s", cat_oops);
 			break;
 		case 'm':
-			printf(cat_oops);
+			printf("%s", cat_oops);
 			return CMD_FAILURE;
 		}
Index: uspace/app/bdsh/cmds/modules/rm/rm.c
===================================================================
--- uspace/app/bdsh/cmds/modules/rm/rm.c	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ uspace/app/bdsh/cmds/modules/rm/rm.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -227,5 +227,5 @@
 		}
 		memset(buff, 0, sizeof(buff));
-		snprintf(buff, len, argv[i]);
+		snprintf(buff, len, "%s", argv[i]);
 
 		scope = rm_scope(buff);
Index: uspace/drv/rootvirt/devices.def
===================================================================
--- uspace/drv/rootvirt/devices.def	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ uspace/drv/rootvirt/devices.def	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -23,6 +23,8 @@
 #endif
 /* Virtual USB host controller. */
+/*
 {
 	.name = "usbhc",
 	.match_id = "usb&hc=vhc"
 },
+*/
Index: uspace/drv/uhci-hcd/Makefile
===================================================================
--- uspace/drv/uhci-hcd/Makefile	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/Makefile	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2010 Vojtech Horky
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+BINARY = uhci-hcd
+
+SOURCES = \
+	callback.c \
+	iface.c \
+	main.c \
+	root_hub.c \
+	transfer_list.c \
+	uhci.c \
+	uhci_struct/transfer_descriptor.c \
+	pci.c 
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/uhci-hcd/callback.c
===================================================================
--- uspace/drv/uhci-hcd/callback.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/callback.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <errno.h>
+#include <mem.h>
+
+#include <usb/debug.h>
+
+#include "callback.h"
+int callback_init(callback_t *instance, device_t *dev,
+  void *buffer, size_t size, usbhc_iface_transfer_in_callback_t func_in,
+  usbhc_iface_transfer_out_callback_t func_out, void *arg)
+{
+	assert(instance);
+	assert(func_in == NULL || func_out == NULL);
+	if (size > 0) {
+		instance->new_buffer = malloc32(size);
+		if (!instance->new_buffer) {
+			usb_log_error("Failed to allocate device acessible buffer.\n");
+			return ENOMEM;
+		}
+		if (func_out)
+			memcpy(instance->new_buffer, buffer, size);
+	} else {
+		instance->new_buffer = NULL;
+	}
+
+
+	instance->callback_out = func_out;
+	instance->callback_in = func_in;
+	instance->old_buffer = buffer;
+	instance->buffer_size = size;
+	instance->dev = dev;
+	instance->arg = arg;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+void callback_run(
+callback_t *instance, usb_transaction_outcome_t outcome, size_t act_size)
+{
+	assert(instance);
+
+	/* update the old buffer */
+	if (instance->new_buffer &&
+	  (instance->new_buffer != instance->old_buffer)) {
+		memcpy(instance->old_buffer, instance->new_buffer, instance->buffer_size);
+		free32(instance->new_buffer);
+		instance->new_buffer = NULL;
+	}
+
+	if (instance->callback_in) {
+		assert(instance->callback_out == NULL);
+		usb_log_debug("Callback in: %p %x %d.\n",
+		  instance->callback_in, outcome, act_size);
+		instance->callback_in(
+		  instance->dev, outcome, act_size, instance->arg);
+	} else {
+		assert(instance->callback_out);
+		assert(instance->callback_in == NULL);
+		usb_log_debug("Callback out: %p %p %x %p .\n",
+		 instance->callback_out, instance->dev, outcome, instance->arg);
+		instance->callback_out(
+		  instance->dev, outcome, instance->arg);
+	}
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/callback.h
===================================================================
--- uspace/drv/uhci-hcd/callback.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/callback.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2010 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_CALLBACK_H
+#define DRV_UHCI_CALLBACK_H
+
+#include <usbhc_iface.h>
+#include <usb/usb.h>
+
+#include "utils/malloc32.h"
+
+typedef struct callback
+{
+	usbhc_iface_transfer_in_callback_t callback_in;
+	usbhc_iface_transfer_out_callback_t callback_out;
+	void *old_buffer;
+	void *new_buffer;
+	void *arg;
+	size_t buffer_size;
+	size_t actual_size;
+	device_t *dev;
+} callback_t;
+
+
+int callback_init(callback_t *instance, device_t *dev,
+  void *buffer, size_t size, usbhc_iface_transfer_in_callback_t func_in,
+  usbhc_iface_transfer_out_callback_t func_out, void *arg);
+
+#define callback_in_init(instance, dev, buffer, size, func, arg) \
+	callback_init(instance, dev, buffer, size, func, NULL, arg)
+
+#define callback_out_init(instance, dev, buffer, size, func, arg) \
+	callback_init(instance, dev, buffer, size, func, NULL, arg)
+
+static inline callback_t *callback_get(device_t *dev,
+  void *buffer, size_t size, usbhc_iface_transfer_in_callback_t func_in,
+  usbhc_iface_transfer_out_callback_t func_out, void *arg)
+{
+	callback_t *instance = malloc(sizeof(callback_t));
+	if (callback_init(instance, dev, buffer, size, func_in, func_out, arg)) {
+		free(instance);
+		instance = NULL;
+	}
+	return instance;
+}
+
+static inline void callback_fini(callback_t *instance)
+{
+	assert(instance);
+	if (instance->new_buffer)
+		free32(instance->new_buffer);
+}
+
+static inline void callback_dispose(callback_t *instance)
+{
+	callback_fini(instance);
+	free(instance);
+}
+
+void callback_run(
+  callback_t *instance, usb_transaction_outcome_t outcome, size_t act_size);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/iface.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky, Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <driver.h>
+#include <remote_usbhc.h>
+
+#include <usb/debug.h>
+
+#include <errno.h>
+
+#include "iface.h"
+#include "uhci.h"
+
+static int get_address(device_t *dev, devman_handle_t handle,
+    usb_address_t *address)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	*address = usb_address_keeping_find(&hc->address_manager, handle);
+	if (*address <= 0)
+	  return *address;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int reserve_default_address(device_t *dev)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	usb_address_keeping_reserve_default(&hc->address_manager);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int release_default_address(device_t *dev)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	usb_address_keeping_release_default(&hc->address_manager);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int request_address(device_t *dev, usb_address_t *address)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	*address = usb_address_keeping_request(&hc->address_manager);
+	if (*address <= 0)
+	  return *address;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int bind_address(
+  device_t *dev, usb_address_t address, devman_handle_t handle)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	usb_address_keeping_devman_bind(&hc->address_manager, address, handle);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int release_address(device_t *dev, usb_address_t address)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	usb_address_keeping_release_default(&hc->address_manager);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int interrupt_out(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	return uhci_transfer(hc, dev, target, USB_TRANSFER_INTERRUPT, 0, USB_PID_OUT,
+		false, data, size, callback, NULL, arg);
+}
+/*----------------------------------------------------------------------------*/
+static int interrupt_in(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	return uhci_transfer(hc, dev, target, USB_TRANSFER_INTERRUPT, 0, USB_PID_IN,
+		false, data, size, NULL, callback, arg);
+}
+/*----------------------------------------------------------------------------*/
+static int control_write_setup(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_SETUP,
+		false, data, size, callback, NULL, arg);
+}
+/*----------------------------------------------------------------------------*/
+static int control_write_data(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 1, USB_PID_OUT,
+		false, data, size, callback, NULL, arg);
+}
+/*----------------------------------------------------------------------------*/
+static int control_write_status(device_t *dev, usb_target_t target,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_IN,
+		false, NULL, 0, NULL, callback, arg);
+}
+/*----------------------------------------------------------------------------*/
+static int control_read_setup(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_SETUP,
+		false, data, size, callback, NULL, arg);
+}
+/*----------------------------------------------------------------------------*/
+static int control_read_data(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 1, USB_PID_IN,
+		false, data, size, NULL, callback, arg);
+}
+/*----------------------------------------------------------------------------*/
+static int control_read_status(device_t *dev, usb_target_t target,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	assert(dev);
+	uhci_t *hc = dev_to_uhci(dev);
+	assert(hc);
+	return uhci_transfer(hc, dev, target, USB_TRANSFER_CONTROL, 0, USB_PID_OUT,
+		false, NULL, 0, callback, NULL, arg);
+}
+
+
+usbhc_iface_t uhci_iface = {
+	.tell_address = get_address,
+
+	.reserve_default_address = reserve_default_address,
+	.release_default_address = release_default_address,
+	.request_address = request_address,
+	.bind_address = bind_address,
+	.release_address = release_address,
+
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+
+	.control_write_setup = control_write_setup,
+	.control_write_data = control_write_data,
+	.control_write_status = control_write_status,
+
+	.control_read_setup = control_read_setup,
+	.control_read_data = control_read_data,
+	.control_read_status = control_read_status
+};
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/iface.h
===================================================================
--- uspace/drv/uhci-hcd/iface.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/iface.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_IFACE_H
+#define DRV_UHCI_IFACE_H
+
+#include <usbhc_iface.h>
+
+usbhc_iface_t uhci_iface;
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/main.c
===================================================================
--- uspace/drv/uhci-hcd/main.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/main.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky, Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <driver.h>
+#include <usb_iface.h>
+
+#include <errno.h>
+
+#include <usb/debug.h>
+
+#include "iface.h"
+#include "pci.h"
+#include "root_hub.h"
+#include "uhci.h"
+
+#define NAME "uhci-hcd"
+
+static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
+{
+	/* This shall be called only for the UHCI itself. */
+	assert(dev->parent == NULL);
+
+	*handle = dev->handle;
+	return EOK;
+}
+
+static usb_iface_t hc_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle
+};
+
+static device_ops_t uhci_ops = {
+	.interfaces[USB_DEV_IFACE] = &hc_usb_iface,
+	.interfaces[USBHC_DEV_IFACE] = &uhci_iface
+};
+
+static int uhci_add_device(device_t *device)
+{
+	assert(device);
+
+	usb_log_info("uhci_add_device() called\n");
+	device->ops = &uhci_ops;
+
+	uintptr_t io_reg_base;
+	size_t io_reg_size;
+	int irq;
+
+	int rc = pci_get_my_registers(device,
+	    &io_reg_base, &io_reg_size, &irq);
+
+	if (rc != EOK) {
+		usb_log_error("Failed(%d) to get I/O registers addresses for device:.\n",
+		    rc, device->handle);
+		return rc;
+	}
+
+	usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
+	    io_reg_base, io_reg_size, irq);
+
+	uhci_t *uhci_hc = malloc(sizeof(uhci_t));
+	if (!uhci_hc) {
+		usb_log_error("Failed to allocaete memory for uhci hcd driver.\n");
+		return ENOMEM;
+	}
+
+	int ret = uhci_init(uhci_hc, (void*)io_reg_base, io_reg_size);
+	if (ret != EOK) {
+		usb_log_error("Failed to init uhci-hcd.\n");
+		return ret;
+	}
+	device_t *rh;
+	ret = setup_root_hub(&rh, device);
+
+	if (ret != EOK) {
+		usb_log_error("Failed to setup uhci root hub.\n");
+		/* TODO: destroy uhci here */
+		return ret;
+	}
+
+	ret = child_device_register(rh, device);
+	if (ret != EOK) {
+		usb_log_error("Failed to register root hub.\n");
+		/* TODO: destroy uhci here */
+		return ret;
+	}
+
+	device->driver_data = uhci_hc;
+
+	return EOK;
+}
+
+static driver_ops_t uhci_driver_ops = {
+	.add_device = uhci_add_device,
+};
+
+static driver_t uhci_driver = {
+	.name = NAME,
+	.driver_ops = &uhci_driver_ops
+};
+
+int main(int argc, char *argv[])
+{
+	/*
+	 * Do some global initializations.
+	 */
+	sleep(5);
+	usb_log_enable(USB_LOG_LEVEL_INFO, NAME);
+
+	return driver_main(&uhci_driver);
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/pci.c
===================================================================
--- uspace/drv/uhci-hcd/pci.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/pci.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/**
+ * @addtogroup drvusbuhci
+ * @{
+ */
+/**
+ * @file
+ * PCI related functions needed by the UHCI driver.
+ */
+#include <errno.h>
+#include <assert.h>
+#include <devman.h>
+#include <device/hw_res.h>
+
+#include "pci.h"
+
+/** Get address of registers and IRQ for given device.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] io_reg_address Base address of the I/O range.
+ * @param[out] io_reg_size Size of the I/O range.
+ * @param[out] irq_no IRQ assigned to the device.
+ * @return Error code.
+ */
+int pci_get_my_registers(device_t *dev,
+    uintptr_t *io_reg_address, size_t *io_reg_size,
+    int *irq_no)
+{
+	assert(dev != NULL);
+
+	int parent_phone = devman_parent_device_connect(dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	int rc;
+
+	hw_resource_list_t hw_resources;
+	rc = hw_res_get_resource_list(parent_phone, &hw_resources);
+	if (rc != EOK) {
+		goto leave;
+	}
+
+	uintptr_t io_address = 0;
+	size_t io_size = 0;
+	bool io_found = false;
+
+	int irq = 0;
+	bool irq_found = false;
+
+	size_t i;
+	for (i = 0; i < hw_resources.count; i++) {
+		hw_resource_t *res = &hw_resources.resources[i];
+		switch (res->type) {
+			case INTERRUPT:
+				irq = res->res.interrupt.irq;
+				irq_found = true;
+				break;
+			case IO_RANGE:
+				io_address = (uintptr_t)
+				    res->res.io_range.address;
+				io_size = res->res.io_range.size;
+				io_found = true;
+				break;
+			default:
+				break;
+		}
+	}
+
+	if (!io_found) {
+		rc = ENOENT;
+		goto leave;
+	}
+
+	if (!irq_found) {
+		rc = ENOENT;
+		goto leave;
+	}
+
+	if (io_reg_address != NULL) {
+		*io_reg_address = io_address;
+	}
+	if (io_reg_size != NULL) {
+		*io_reg_size = io_size;
+	}
+	if (irq_no != NULL) {
+		*irq_no = irq;
+	}
+
+	rc = EOK;
+leave:
+	ipc_hangup(parent_phone);
+
+	return rc;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/pci.h
===================================================================
--- uspace/drv/uhci-hcd/pci.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/pci.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_PCI_H
+#define DRV_UHCI_PCI_H
+
+#include <driver.h>
+
+int pci_get_my_registers(device_t *, uintptr_t *, size_t *, int *);
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/uhci-hcd/root_hub.c
===================================================================
--- uspace/drv/uhci-hcd/root_hub.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/root_hub.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include <usb_iface.h>
+
+#include <usb/debug.h>
+
+#include "root_hub.h"
+/*----------------------------------------------------------------------------*/
+static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
+{
+  assert(dev);
+  assert(dev->parent != NULL);
+
+  device_t *parent = dev->parent;
+
+  if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
+    usb_iface_t *usb_iface
+        = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
+    assert(usb_iface != NULL);
+    if (usb_iface->get_hc_handle) {
+      int rc = usb_iface->get_hc_handle(parent, handle);
+      return rc;
+    }
+  }
+
+  return ENOTSUP;
+}
+/*----------------------------------------------------------------------------*/
+static usb_iface_t usb_iface = {
+  .get_hc_handle = usb_iface_get_hc_handle
+};
+
+static device_ops_t rh_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface
+};
+
+int setup_root_hub(device_t **device, device_t *hc)
+{
+	assert(device);
+	device_t *hub = create_device();
+	if (!hub) {
+		usb_log_error("Failed to create root hub device structure.\n");
+		return ENOMEM;
+	}
+	char *name;
+	int ret = asprintf(&name, "UHCI Root Hub");
+	if (ret < 0) {
+		usb_log_error("Failed to create root hub name.\n");
+		free(hub);
+		return ENOMEM;
+	}
+
+	char *match_str;
+	ret = asprintf(&match_str, "usb&uhci&root-hub");
+	if (ret < 0) {
+		usb_log_error("Failed to create root hub match string.\n");
+		free(hub);
+		free(name);
+		return ENOMEM;
+	}
+
+	match_id_t *match_id = create_match_id();
+	if (!match_id) {
+		usb_log_error("Failed to create root hub match id.\n");
+		free(hub);
+		free(match_str);
+		return ENOMEM;
+	}
+	match_id->id = match_str;
+	match_id->score = 90;
+
+	add_match_id(&hub->match_ids, match_id);
+	hub->name = name;
+	hub->parent = hc;
+	hub->ops = &rh_ops;
+
+	*device = hub;
+	return EOK;
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/root_hub.h
===================================================================
--- uspace/drv/uhci-hcd/root_hub.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/root_hub.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_ROOT_HUB_H
+#define DRV_UHCI_ROOT_HUB_H
+
+#include <driver.h>
+
+int setup_root_hub(device_t **device, device_t *hc);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/transfer_list.c
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <errno.h>
+
+#include <usb/debug.h>
+
+#include "transfer_list.h"
+
+int transfer_list_init(transfer_list_t *instance, const char *name)
+{
+	assert(instance);
+	instance->first = NULL;
+	instance->last = NULL;
+	instance->next = NULL;
+	instance->name = name;
+	instance->queue_head = queue_head_get();
+	if (!instance->queue_head) {
+		usb_log_error("Failed to allocate queue head.\n");
+		return ENOMEM;
+	}
+	instance->queue_head_pa = (uintptr_t)addr_to_phys(instance->queue_head);
+
+	queue_head_init(instance->queue_head);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
+{
+	assert(instance);
+	assert(next);
+	instance->next = next;
+	if (!instance->queue_head)
+		return;
+	queue_head_add_next(instance->queue_head, next->queue_head_pa);
+}
+/*----------------------------------------------------------------------------*/
+int transfer_list_append(
+  transfer_list_t *instance, transfer_descriptor_t *transfer)
+{
+	assert(instance);
+	assert(transfer);
+
+	uint32_t pa = (uintptr_t)addr_to_phys(transfer);
+	assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
+
+	/* empty list */
+	if (instance->first == NULL) {
+		assert(instance->last == NULL);
+		instance->first = instance->last = transfer;
+	} else {
+		assert(instance->last);
+		instance->last->next_va = transfer;
+
+		assert(instance->last->next & LINK_POINTER_TERMINATE_FLAG);
+		instance->last->next = (pa & LINK_POINTER_ADDRESS_MASK);
+		instance->last = transfer;
+	}
+
+	assert(instance->queue_head);
+	if (instance->queue_head->element & LINK_POINTER_TERMINATE_FLAG) {
+		instance->queue_head->element = (pa & LINK_POINTER_ADDRESS_MASK);
+	}
+	usb_log_debug("Successfully added transfer to the hc queue %s.\n",
+	  instance->name);
+	return EOK;
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/transfer_list.h
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/transfer_list.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_TRANSFER_LIST_H
+#define DRV_UHCI_TRANSFER_LIST_H
+
+#include "uhci_struct/queue_head.h"
+#include "uhci_struct/transfer_descriptor.h"
+
+typedef struct transfer_list
+{
+	transfer_descriptor_t *first;
+	transfer_descriptor_t *last;
+	queue_head_t *queue_head;
+	uint32_t queue_head_pa;
+	struct transfer_list *next;
+	const char *name;
+} transfer_list_t;
+
+int transfer_list_init(transfer_list_t *instance, const char *name);
+
+void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
+
+static inline void transfer_list_fini(transfer_list_t *instance)
+{
+	assert(instance);
+	queue_head_dispose(instance->queue_head);
+}
+
+int transfer_list_append(
+  transfer_list_t *instance, transfer_descriptor_t *transfer);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/transfers.c
===================================================================
--- uspace/drv/uhci-hcd/transfers.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/transfers.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <usb/hcdhubd.h>
+#include <errno.h>
+
+#include "uhci.h"
+
+static int enqueue_transfer_out(device_t *dev,
+    usb_target_t target, usb_transfer_type_t transfer_type,
+    void *buffer, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	printf(NAME ": transfer OUT [%d.%d (%s); %zu]\n",
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transfer_type),
+	    size);
+
+	return ENOTSUP;
+}
+
+static int enqueue_transfer_setup(device_t *dev,
+    usb_target_t target, usb_transfer_type_t transfer_type,
+    void *buffer, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	printf(NAME ": transfer SETUP [%d.%d (%s); %zu]\n",
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transfer_type),
+	    size);
+
+	return ENOTSUP;
+}
+
+static int enqueue_transfer_in(device_t *dev,
+    usb_target_t target, usb_transfer_type_t transfer_type,
+    void *buffer, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	printf(NAME ": transfer IN [%d.%d (%s); %zu]\n",
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transfer_type),
+	    size);
+
+	return ENOTSUP;
+}
+
+
+static int get_address(device_t *dev, devman_handle_t handle,
+    usb_address_t *address)
+{
+	return ENOTSUP;
+}
+
+static int interrupt_out(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_out(dev, target, USB_TRANSFER_INTERRUPT,
+	    data, size,
+	    callback, arg);
+}
+
+static int interrupt_in(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	return enqueue_transfer_in(dev, target, USB_TRANSFER_INTERRUPT,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_write_setup(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_write_data(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_write_status(device_t *dev, usb_target_t target,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
+	    NULL, 0,
+	    callback, arg);
+}
+
+static int control_read_setup(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_read_data(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_read_status(device_t *dev, usb_target_t target,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
+	    NULL, 0,
+	    callback, arg);
+}
+
+
+usbhc_iface_t uhci_iface = {
+	.tell_address = get_address,
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+	.control_write_setup = control_write_setup,
+	.control_write_data = control_write_data,
+	.control_write_status = control_write_status,
+	.control_read_setup = control_read_setup,
+	.control_read_data = control_read_data,
+	.control_read_status = control_read_status
+};
Index: uspace/drv/uhci-hcd/uhci-hcd.ma
===================================================================
--- uspace/drv/uhci-hcd/uhci-hcd.ma	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/uhci-hcd.ma	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,2 @@
+10 pci/ven=8086&dev=7020
+
Index: uspace/drv/uhci-hcd/uhci.c
===================================================================
--- uspace/drv/uhci-hcd/uhci.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/uhci.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <errno.h>
+
+#include <usb/debug.h>
+#include <usb/usb.h>
+
+#include "uhci.h"
+
+static int uhci_init_transfer_lists(uhci_t *instance);
+static int uhci_clean_finished(void *arg);
+static int uhci_debug_checker(void *arg);
+
+int uhci_init(uhci_t *instance, void *regs, size_t reg_size)
+{
+#define CHECK_RET_RETURN(message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		return ret; \
+	} else (void) 0
+
+	/* init address keeper(libusb) */
+	usb_address_keeping_init(&instance->address_manager, USB11_ADDRESS_MAX);
+	usb_log_debug("Initialized address manager.\n");
+
+	/* allow access to hc control registers */
+	regs_t *io;
+	assert(reg_size >= sizeof(regs_t));
+	int ret = pio_enable(regs, reg_size, (void**)&io);
+	CHECK_RET_RETURN("Failed to gain access to registers at %p.\n", io);
+	instance->registers = io;
+	usb_log_debug("Device registers accessible.\n");
+
+	/* init transfer lists */
+	ret = uhci_init_transfer_lists(instance);
+	CHECK_RET_RETURN("Failed to initialize transfer lists.\n");
+	usb_log_debug("Transfer lists initialized.\n");
+
+
+	usb_log_debug("Initializing frame list.\n");
+	instance->frame_list = get_page();
+	ret = instance ? EOK : ENOMEM;
+	CHECK_RET_RETURN("Failed to get frame list page.\n");
+
+	/* initialize all frames to point to the first queue head */
+	const uint32_t queue =
+	  instance->transfers_interrupt.queue_head_pa
+	  | LINK_POINTER_QUEUE_HEAD_FLAG;
+	unsigned i = 0;
+	for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
+		instance->frame_list[i] = queue;
+	}
+
+	const uintptr_t pa = (uintptr_t)addr_to_phys(instance->frame_list);
+
+	pio_write_32(&instance->registers->flbaseadd, (uint32_t)pa);
+
+	instance->cleaner = fibril_create(uhci_clean_finished, instance);
+	fibril_add_ready(instance->cleaner);
+
+	instance->debug_checker = fibril_create(uhci_debug_checker, instance);
+	fibril_add_ready(instance->debug_checker);
+
+	/* Start the hc with large(64b) packet FSBR */
+	pio_write_16(&instance->registers->usbcmd,
+	    UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET);
+	usb_log_debug("Started UHCI HC.\n");
+
+	uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
+	cmd |= UHCI_CMD_DEBUG;
+	pio_write_16(&instance->registers->usbcmd, cmd);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+int uhci_init_transfer_lists(uhci_t *instance)
+{
+	assert(instance);
+
+	/* initialize */
+	int ret;
+	ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
+	assert(ret == EOK);
+	ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL");
+	assert(ret == EOK);
+	ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW");
+	assert(ret == EOK);
+	ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
+	assert(ret == EOK);
+
+	transfer_list_set_next(&instance->transfers_control_full,
+		&instance->transfers_bulk_full);
+	transfer_list_set_next(&instance->transfers_control_slow,
+		&instance->transfers_control_full);
+	transfer_list_set_next(&instance->transfers_interrupt,
+		&instance->transfers_control_slow);
+
+	/*FSBR*/
+#ifdef FSBR
+	transfer_list_set_next(&instance->transfers_bulk_full,
+		&instance->transfers_control_full);
+#endif
+
+	instance->transfers[0][USB_TRANSFER_INTERRUPT] =
+	  &instance->transfers_interrupt;
+	instance->transfers[1][USB_TRANSFER_INTERRUPT] =
+	  &instance->transfers_interrupt;
+	instance->transfers[0][USB_TRANSFER_CONTROL] =
+	  &instance->transfers_control_full;
+	instance->transfers[1][USB_TRANSFER_CONTROL] =
+	  &instance->transfers_control_slow;
+	instance->transfers[0][USB_TRANSFER_CONTROL] =
+	  &instance->transfers_control_full;
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+int uhci_transfer(
+  uhci_t *instance,
+  device_t *dev,
+  usb_target_t target,
+  usb_transfer_type_t transfer_type,
+	bool toggle,
+  usb_packet_id pid,
+	bool low_speed,
+  void *buffer, size_t size,
+  usbhc_iface_transfer_out_callback_t callback_out,
+  usbhc_iface_transfer_in_callback_t callback_in,
+  void *arg)
+{
+	// TODO: Add support for isochronous transfers
+	if (transfer_type == USB_TRANSFER_ISOCHRONOUS) {
+		usb_log_warning("ISO transfer not supported.\n");
+		return ENOTSUP;
+	}
+
+	if (transfer_type == USB_TRANSFER_INTERRUPT
+	  && size >= 64) {
+		usb_log_warning("Interrupt transfer too big %zu.\n", size);
+		return ENOTSUP;
+	}
+
+	if (size >= 1024) {
+		usb_log_warning("Transfer too big.\n");
+		return ENOTSUP;
+	}
+	transfer_list_t *list = instance->transfers[low_speed][transfer_type];
+	if (!list) {
+		usb_log_warning("UNSUPPORTED transfer %d-%d.\n", low_speed, transfer_type);
+		return ENOTSUP;
+	}
+
+	transfer_descriptor_t *td = NULL;
+	callback_t *job = NULL;
+	int ret = EOK;
+	assert(dev);
+
+#define CHECK_RET_TRANS_FREE_JOB_TD(message) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		if (job) { \
+			callback_dispose(job); \
+		} \
+		if (td) { free32(td); } \
+		return ret; \
+	} else (void) 0
+
+	job = callback_get(dev, buffer, size, callback_in, callback_out, arg);
+	ret = job ? EOK : ENOMEM;
+	CHECK_RET_TRANS_FREE_JOB_TD("Failed to allocate callback structure.\n");
+
+	td = transfer_descriptor_get(3, size, false, target, pid, job->new_buffer);
+	ret = td ? EOK : ENOMEM;
+	CHECK_RET_TRANS_FREE_JOB_TD("Failed to setup transfer descriptor.\n");
+
+	td->callback = job;
+
+
+	usb_log_debug("Appending a new transfer to queue %s.\n", list->name);
+
+	ret = transfer_list_append(list, td);
+	CHECK_RET_TRANS_FREE_JOB_TD("Failed to append transfer descriptor.\n");
+
+	return EOK;
+}
+/*---------------------------------------------------------------------------*/
+int uhci_clean_finished(void* arg)
+{
+	usb_log_debug("Started cleaning fibril.\n");
+	uhci_t *instance = (uhci_t*)arg;
+	assert(instance);
+
+	while(1) {
+		usb_log_debug("Running cleaning fibril on: %p.\n", instance);
+		/* iterate all transfer queues */
+		transfer_list_t *current_list = &instance->transfers_interrupt;
+		while (current_list) {
+			/* Remove inactive transfers from the top of the queue
+			 * TODO: should I reach queue head or is this enough? */
+			volatile transfer_descriptor_t * it =
+				current_list->first;
+			usb_log_debug("Running cleaning fibril on queue: %s (%s).\n",
+				current_list->name, it ? "SOMETHING" : "EMPTY");
+
+			if (it) {
+				usb_log_debug("First in queue: %p (%x) PA:%x.\n",
+					it, it->status, addr_to_phys((void*)it) );
+				usb_log_debug("First to send: %x\n",
+					(current_list->queue_head->element) );
+			}
+
+			while (current_list->first &&
+			 !(current_list->first->status & TD_STATUS_ERROR_ACTIVE)) {
+				transfer_descriptor_t *transfer = current_list->first;
+				usb_log_info("Inactive transfer calling callback with status %x.\n",
+				  transfer->status);
+				current_list->first = transfer->next_va;
+				transfer_descriptor_dispose(transfer);
+			}
+			if (!current_list->first)
+				current_list->last = current_list->first;
+
+			current_list = current_list->next;
+		}
+		async_usleep(UHCI_CLEANER_TIMEOUT);
+	}
+	return EOK;
+}
+/*---------------------------------------------------------------------------*/
+int uhci_debug_checker(void *arg)
+{
+	uhci_t *instance = (uhci_t*)arg;
+	assert(instance);
+	while (1) {
+		uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
+		uint16_t sts = pio_read_16(&instance->registers->usbsts);
+		usb_log_debug("Command register: %X Status register: %X\n", cmd, sts);
+
+		uintptr_t frame_list = pio_read_32(&instance->registers->flbaseadd);
+		if (frame_list != (uintptr_t)addr_to_phys(instance->frame_list)) {
+			usb_log_debug("Framelist address: %p vs. %p.\n",
+				frame_list, addr_to_phys(instance->frame_list));
+		}
+		int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
+		usb_log_debug2("Framelist item: %d \n", frnum );
+
+		queue_head_t* qh = instance->transfers_interrupt.queue_head;
+
+		if ((instance->frame_list[frnum] & (~0xf)) != (uintptr_t)addr_to_phys(qh)) {
+			usb_log_debug("Interrupt QH: %p vs. %p.\n",
+				instance->frame_list[frnum] & (~0xf), addr_to_phys(qh));
+		}
+
+		if ((qh->next_queue & (~0xf))
+		  != (uintptr_t)addr_to_phys(instance->transfers_control_slow.queue_head)) {
+			usb_log_debug("Control Slow QH: %p vs. %p.\n", qh->next_queue & (~0xf),
+				addr_to_phys(instance->transfers_control_slow.queue_head));
+		}
+		qh = instance->transfers_control_slow.queue_head;
+
+		if ((qh->next_queue & (~0xf))
+		  != (uintptr_t)addr_to_phys(instance->transfers_control_full.queue_head)) {
+			usb_log_debug("Control Full QH: %p vs. %p.\n", qh->next_queue & (~0xf),
+				addr_to_phys(instance->transfers_control_full.queue_head));\
+		}
+		qh = instance->transfers_control_full.queue_head;
+
+		if ((qh->next_queue & (~0xf))
+		  != (uintptr_t)addr_to_phys(instance->transfers_bulk_full.queue_head)) {
+			usb_log_debug("Bulk QH: %p vs. %p.\n", qh->next_queue & (~0xf),
+				addr_to_phys(instance->transfers_bulk_full.queue_head));
+		}
+/*
+	uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
+	cmd |= UHCI_CMD_RUN_STOP;
+	pio_write_16(&instance->registers->usbcmd, cmd);
+*/
+		async_usleep(UHCI_DEBUGER_TIMEOUT);
+	}
+	return 0;
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/uhci.h
===================================================================
--- uspace/drv/uhci-hcd/uhci.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/uhci.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2010 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_UHCI_H
+#define DRV_UHCI_UHCI_H
+
+#include <fibril.h>
+
+#include <usb/addrkeep.h>
+#include <usbhc_iface.h>
+
+#include "transfer_list.h"
+
+typedef struct uhci_regs {
+	uint16_t usbcmd;
+#define UHCI_CMD_MAX_PACKET (1 << 7)
+#define UHCI_CMD_CONFIGURE  (1 << 6)
+#define UHCI_CMD_DEBUG  (1 << 5)
+#define UHCI_CMD_FORCE_GLOBAL_RESUME  (1 << 4)
+#define UHCI_CMD_FORCE_GLOBAL_SUSPEND  (1 << 3)
+#define UHCI_CMD_GLOBAL_RESET  (1 << 2)
+#define UHCI_CMD_HCRESET  (1 << 1)
+#define UHCI_CMD_RUN_STOP  (1 << 0)
+
+	uint16_t usbsts;
+#define UHCI_STATUS_HALTED (1 << 5)
+#define UHCI_STATUS_PROCESS_ERROR (1 << 4)
+#define UHCI_STATUS_SYSTEM_ERROR (1 << 3)
+#define UHCI_STATUS_RESUME (1 << 2)
+#define UHCI_STATUS_ERROR_INTERRUPT (1 << 1)
+#define UHCI_STATUS_INTERRUPT (1 << 0)
+
+	uint16_t usbintr;
+	uint16_t frnum;
+	uint32_t flbaseadd;
+	uint8_t sofmod;
+} regs_t;
+
+#define TRANSFER_QUEUES 4
+#define UHCI_FRAME_LIST_COUNT 1024
+#define UHCI_CLEANER_TIMEOUT 10000
+#define UHCI_DEBUGER_TIMEOUT 500000
+
+typedef struct uhci {
+	usb_address_keeping_t address_manager;
+	volatile regs_t *registers;
+
+	link_pointer_t *frame_list;
+
+	transfer_list_t transfers_bulk_full;
+	transfer_list_t transfers_control_full;
+	transfer_list_t transfers_control_slow;
+	transfer_list_t transfers_interrupt;
+
+	transfer_list_t *transfers[2][4];
+
+	fid_t cleaner;
+	fid_t debug_checker;
+} uhci_t;
+
+/* init uhci specifics in device.driver_data */
+int uhci_init(uhci_t *instance, void *regs, size_t reg_size);
+
+int uhci_fini(uhci_t *device);
+
+int uhci_transfer(
+  uhci_t *instance,
+  device_t *dev,
+  usb_target_t target,
+  usb_transfer_type_t transfer_type,
+	bool toggle,
+  usb_packet_id pid,
+	bool low_speed,
+  void *buffer, size_t size,
+  usbhc_iface_transfer_out_callback_t callback_out,
+  usbhc_iface_transfer_in_callback_t callback_in,
+  void *arg );
+
+static inline uhci_t * dev_to_uhci(device_t *dev)
+	{ return (uhci_t*)dev->driver_data; }
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/uhci_struct/link_pointer.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/link_pointer.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/uhci_struct/link_pointer.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_LINK_POINTER_H
+#define DRV_UHCI_LINK_POINTER_H
+
+/* UHCI link pointer, used by many data structures */
+typedef uint32_t link_pointer_t;
+
+#define LINK_POINTER_TERMINATE_FLAG (1 << 0)
+#define LINK_POINTER_QUEUE_HEAD_FLAG (1 << 1)
+#define LINK_POINTER_ZERO_BIT_FLAG (1 << 2)
+#define LINK_POINTER_VERTICAL_FLAG (1 << 2)
+#define LINK_POINTER_RESERVED_FLAG (1 << 3)
+
+#define LINK_POINTER_ADDRESS_MASK 0xfffffff0 /* upper 28 bits */
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/uhci-hcd/uhci_struct/queue_head.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/queue_head.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/uhci_struct/queue_head.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,75 @@
+
+/*
+ * Copyright (c) 2010 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_QH_H
+#define DRV_UHCI_QH_H
+
+/* libc */
+#include <assert.h>
+
+#include "link_pointer.h"
+#include "utils/malloc32.h"
+
+typedef struct queue_head {
+	link_pointer_t next_queue;
+	link_pointer_t element;
+} __attribute__((packed)) queue_head_t;
+
+static inline void queue_head_init(queue_head_t *instance)
+{
+	assert(instance);
+
+	instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
+	instance->next_queue = 0 | LINK_POINTER_TERMINATE_FLAG;
+}
+
+static inline void queue_head_add_next(queue_head_t *instance, uint32_t next_queue_pa)
+{
+	if (next_queue_pa) {
+		instance->next_queue = (next_queue_pa & LINK_POINTER_ADDRESS_MASK)
+		  | LINK_POINTER_QUEUE_HEAD_FLAG;
+	}
+}
+
+static inline queue_head_t * queue_head_get()
+	{ return malloc32(sizeof(queue_head_t)); }
+
+static inline void queue_head_dispose(queue_head_t *head)
+	{ free32(head); }
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <usb/debug.h>
+
+#include "transfer_descriptor.h"
+
+void transfer_descriptor_init(transfer_descriptor_t *instance,
+  int error_count, size_t size, bool isochronous, usb_target_t target,
+	int pid, void *buffer)
+{
+	assert(instance);
+
+	instance->next =
+	  0 | LINK_POINTER_TERMINATE_FLAG;
+
+
+	assert(size < 1024);
+	instance->status = 0
+	  | ((error_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
+	  | TD_STATUS_ERROR_ACTIVE;
+
+	instance->device = 0
+		| (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
+		| ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
+		| ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
+		| ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
+
+	instance->buffer_ptr = 0;
+
+	instance->next_va = NULL;
+	instance->callback = NULL;
+
+	if (size) {
+		instance->buffer_ptr = (uintptr_t)addr_to_phys(buffer);
+	}
+
+	usb_log_info("Created TD: %X:%X:%X:%X(%p).\n",
+		instance->next, instance->status, instance->device,
+	  instance->buffer_ptr, buffer);
+#if 0
+	if (size) {
+		unsigned char * buff = buffer;
+		uhci_print_verbose("TD Buffer dump(%p-%dB): ", buffer, size);
+		unsigned i = 0;
+		/* TODO: Verbose? */
+		for (; i < size; ++i) {
+			printf((i & 1) ? "%x " : "%x", buff[i]);
+		}
+		printf("\n");
+	}
+#endif
+}
+
+static inline usb_transaction_outcome_t convert_outcome(uint32_t status)
+{
+	/*TODO: refactor into something sane */
+	/*TODO: add additional usb_errors to usb_outcome_t */
+
+	if (status & TD_STATUS_ERROR_STALLED)
+		return USB_OUTCOME_CRCERROR;
+
+	if (status & TD_STATUS_ERROR_BUFFER)
+		return USB_OUTCOME_CRCERROR;
+
+	if (status & TD_STATUS_ERROR_BABBLE)
+		return USB_OUTCOME_BABBLE;
+
+	if (status & TD_STATUS_ERROR_NAK)
+		return USB_OUTCOME_CRCERROR;
+
+  if (status & TD_STATUS_ERROR_CRC)
+		return USB_OUTCOME_CRCERROR;
+
+	if (status & TD_STATUS_ERROR_BIT_STUFF)
+		return USB_OUTCOME_CRCERROR;
+
+	assert((((status >> TD_STATUS_ERROR_POS) & TD_STATUS_ERROR_MASK)
+	| TD_STATUS_ERROR_RESERVED) == TD_STATUS_ERROR_RESERVED);
+	return USB_OUTCOME_OK;
+}
+
+void transfer_descriptor_fini(transfer_descriptor_t *instance)
+{
+	assert(instance);
+	callback_run(instance->callback,
+		convert_outcome(instance->status),
+		((instance->status >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK
+	);
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2010 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_TRANSFER_DESCRIPTOR_H
+#define DRV_UHCI_TRANSFER_DESCRIPTOR_H
+
+#include <mem.h>
+#include <usb/usb.h>
+
+#include "utils/malloc32.h"
+#include "callback.h"
+#include "link_pointer.h"
+
+/** UHCI Transfer Descriptor */
+typedef struct transfer_descriptor {
+	link_pointer_t next;
+
+	volatile uint32_t status;
+
+#define TD_STATUS_RESERVED_MASK 0xc000f800
+#define TD_STATUS_SPD_FLAG ( 1 << 29 )
+#define TD_STATUS_ERROR_COUNT_POS ( 27 )
+#define TD_STATUS_ERROR_COUNT_MASK ( 0x3 )
+#define TD_STATUS_ERROR_COUNT_DEFAULT 3
+#define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 )
+#define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 )
+#define TD_STATUS_COMPLETE_INTERRUPT_FLAG ( 1 << 24 )
+
+#define TD_STATUS_ERROR_ACTIVE ( 1 << 23 )
+#define TD_STATUS_ERROR_STALLED ( 1 << 22 )
+#define TD_STATUS_ERROR_BUFFER ( 1 << 21 )
+#define TD_STATUS_ERROR_BABBLE ( 1 << 20 )
+#define TD_STATUS_ERROR_NAK ( 1 << 19 )
+#define TD_STATUS_ERROR_CRC ( 1 << 18 )
+#define TD_STATUS_ERROR_BIT_STUFF ( 1 << 17 )
+#define TD_STATUS_ERROR_RESERVED ( 1 << 16 )
+#define TD_STATUS_ERROR_POS 16
+#define TD_STATUS_ERROR_MASK ( 0xff )
+
+#define TD_STATUS_ACTLEN_POS 0
+#define TD_STATUS_ACTLEN_MASK 0x7ff
+
+	volatile uint32_t device;
+
+#define TD_DEVICE_MAXLEN_POS 21
+#define TD_DEVICE_MAXLEN_MASK ( 0x7ff )
+#define TD_DEVICE_RESERVED_FLAG ( 1 << 20 )
+#define TD_DEVICE_DATA_TOGGLE_ONE_FLAG ( 1 << 19 )
+#define TD_DEVICE_ENDPOINT_POS 15
+#define TD_DEVICE_ENDPOINT_MASK ( 0xf )
+#define TD_DEVICE_ADDRESS_POS 8
+#define TD_DEVICE_ADDRESS_MASK ( 0x7f )
+#define TD_DEVICE_PID_POS 0
+#define TD_DEVICE_PID_MASK ( 0xff )
+
+	volatile uint32_t buffer_ptr;
+
+	/* there is 16 bytes of data available here
+	 * those are used to store callback pointer
+	 * and next pointer. Thus, there is some free space
+	 * on 32bits systems.
+	 */
+	struct transfer_descriptor *next_va;
+	callback_t *callback;
+} __attribute__((packed)) transfer_descriptor_t;
+
+
+void transfer_descriptor_init(transfer_descriptor_t *instance,
+  int error_count, size_t size, bool isochronous, usb_target_t target,
+	int pid, void *buffer);
+
+static inline transfer_descriptor_t * transfer_descriptor_get(
+  int error_count, size_t size, bool isochronous, usb_target_t target,
+  int pid, void *buffer)
+{
+	transfer_descriptor_t * instance =
+	  malloc32(sizeof(transfer_descriptor_t));
+
+	if (instance)
+		transfer_descriptor_init(
+		  instance, error_count, size, isochronous, target, pid, buffer);
+	return instance;
+}
+
+void transfer_descriptor_fini(transfer_descriptor_t *instance);
+
+static inline void transfer_descriptor_dispose(transfer_descriptor_t *instance)
+{
+	assert(instance);
+	transfer_descriptor_fini(instance);
+	free32(instance);
+}
+
+static inline void transfer_descriptor_append(
+  transfer_descriptor_t *instance, transfer_descriptor_t *item)
+{
+	assert(instance);
+	instance->next_va = item;
+	instance->next = (uintptr_t)addr_to_phys( item ) & LINK_POINTER_ADDRESS_MASK;
+}
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/utils/malloc32.h
===================================================================
--- uspace/drv/uhci-hcd/utils/malloc32.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-hcd/utils/malloc32.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_TRANSLATOR_H
+#define DRV_UHCI_TRANSLATOR_H
+
+#include <usb/usbmem.h>
+
+#include <assert.h>
+#include <malloc.h>
+#include <mem.h>
+#include <as.h>
+
+#define UHCI_STRCUTURES_ALIGNMENT 16
+#define UHCI_REQUIRED_PAGE_SIZE 4096
+
+static inline void * addr_to_phys(void *addr)
+{
+	uintptr_t result;
+	int ret = as_get_physical_mapping(addr, &result);
+
+	assert(ret == 0);
+	return (void*)(result | ((uintptr_t)addr & 0xfff));
+}
+
+static inline void * malloc32(size_t size)
+	{ return memalign(UHCI_STRCUTURES_ALIGNMENT, size); }
+
+static inline void * get_page()
+{
+	void * free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE);
+	assert(free_address);
+	if (free_address == 0)
+		return 0;
+	void* ret =
+	  as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
+		  AS_AREA_READ | AS_AREA_WRITE);
+	if (ret != free_address)
+		return 0;
+	return ret;
+}
+
+static inline void free32(void *addr)
+	{ if (addr) free(addr); }
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/Makefile
===================================================================
--- uspace/drv/uhci-rhd/Makefile	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-rhd/Makefile	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2010 Jan Vesely
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+BINARY = uhci-rhd
+
+SOURCES = \
+	main.c \
+	port.c \
+	port_status.c \
+	root_hub.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/uhci-rhd/main.c
===================================================================
--- uspace/drv/uhci-rhd/main.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-rhd/main.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky, Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <driver.h>
+#include <usb_iface.h>
+
+#include <errno.h>
+
+#include <usb/debug.h>
+
+#include "root_hub.h"
+
+#define NAME "uhci-rhd"
+
+static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
+{
+	assert(dev);
+	assert(dev->driver_data);
+	assert(handle);
+
+	*handle = ((uhci_root_hub_t*)dev->driver_data)->hc_handle;
+	usb_log_debug("Answering HC handle: %d.\n", *handle);
+
+	return EOK;
+}
+
+static usb_iface_t uhci_rh_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle
+};
+
+static device_ops_t uhci_rh_ops = {
+	.interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface,
+};
+
+static int uhci_rh_add_device(device_t *device)
+{
+	if (!device)
+		return ENOTSUP;
+
+	usb_log_debug2("%s called device %d\n", __FUNCTION__, device->handle);
+	device->ops = &uhci_rh_ops;
+
+	uhci_root_hub_t *rh = malloc(sizeof(uhci_root_hub_t));
+	if (!rh) {
+		usb_log_error("Failed to allocate memory for driver instance.\n");
+		return ENOMEM;
+	}
+
+	/* TODO: get register values from hc */
+	int ret = uhci_root_hub_init(rh, (void*)0xc030, 4, device);
+	if (ret != EOK) {
+		usb_log_error("Failed(%d) to initialize driver instance.\n", ret);
+		free(rh);
+		return ret;
+	}
+
+	device->driver_data = rh;
+	usb_log_info("Sucessfully initialized driver instance for device:%d.\n",
+	    device->handle);
+	return EOK;
+}
+
+static driver_ops_t uhci_rh_driver_ops = {
+	.add_device = uhci_rh_add_device,
+};
+
+static driver_t uhci_rh_driver = {
+	.name = NAME,
+	.driver_ops = &uhci_rh_driver_ops
+};
+
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+	return driver_main(&uhci_rh_driver);
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/port.c
===================================================================
--- uspace/drv/uhci-rhd/port.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-rhd/port.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <errno.h>
+
+#include <usb/usb.h>    /* usb_address_t */
+#include <usb/usbdrv.h> /* usb_drv_*     */
+#include <usb/debug.h>
+
+#include "port.h"
+#include "port_status.h"
+
+static int uhci_port_new_device(uhci_port_t *port);
+static int uhci_port_remove_device(uhci_port_t *port);
+static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
+static int uhci_port_check(void *port);
+
+int uhci_port_init(
+  uhci_port_t *port, port_status_t *address, unsigned number,
+  unsigned usec, device_t *rh, int parent_phone)
+{
+	assert(port);
+	port->address = address;
+	port->number = number;
+	port->wait_period_usec = usec;
+	port->attached_device = 0;
+	port->rh = rh;
+	port->hc_phone = parent_phone;
+
+	port->checker = fibril_create(uhci_port_check, port);
+	if (port->checker == 0) {
+		usb_log_error(": failed to launch root hub fibril.");
+		return ENOMEM;
+	}
+	fibril_add_ready(port->checker);
+	usb_log_debug(
+	  "Added fibril for port %d: %p.\n", number, port->checker);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+void uhci_port_fini(uhci_port_t *port)
+{
+// TODO: destroy fibril
+// TODO: hangup phone
+//	fibril_teardown(port->checker);
+	return;
+}
+/*----------------------------------------------------------------------------*/
+int uhci_port_check(void *port)
+{
+	uhci_port_t *port_instance = port;
+	assert(port_instance);
+
+	while (1) {
+		usb_log_debug("Port(%d) status address %p:\n",
+		  port_instance->number, port_instance->address);
+
+		/* read register value */
+		port_status_t port_status =
+			port_status_read(port_instance->address);
+
+		/* debug print */
+		usb_log_info("Port(%d) status %#.4x\n",
+		  port_instance->number, port_status);
+		print_port_status(port_status);
+
+		if (port_status & STATUS_CONNECTED_CHANGED) {
+			if (port_status & STATUS_CONNECTED) {
+				/* new device */
+				uhci_port_new_device(port_instance);
+			} else {
+				uhci_port_remove_device(port_instance);
+			}
+		}
+		async_usleep(port_instance->wait_period_usec);
+	}
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int uhci_port_new_device(uhci_port_t *port)
+{
+	assert(port);
+	assert(port->hc_phone);
+
+	usb_log_info("Adding new device on port %d.\n", port->number);
+
+	/* get address of the future device */
+	const usb_address_t usb_address = usb_drv_request_address(port->hc_phone);
+
+	if (usb_address <= 0) {
+		usb_log_error("Recieved invalid address(%d).\n", usb_address);
+		return usb_address;
+	}
+	usb_log_debug("Sucessfully obtained address %d for port %d.\n",
+	    usb_address, port->number);
+
+	/* get default address */
+	int ret = usb_drv_reserve_default_address(port->hc_phone);
+	if (ret != EOK) {
+		usb_log_error("Failed to reserve default address on port %d.\n",
+		    port->number);
+		int ret2 =
+		  usb_drv_release_address(port->hc_phone, usb_address);
+		if (ret2 != EOK) {
+			usb_log_fatal("Failed to return requested address on port %d.\n",
+			   port->number);
+			return ret2;
+		}
+		usb_log_debug("Successfully returned reserved address on port %d.\n",
+			port->number);
+		return ret;
+	}
+	usb_log_debug("Sucessfully obtained default address for port %d.\n",
+	    port->number);
+
+	/*
+	 * the host then waits for at least 100 ms to allow completion of
+	 * an insertion process and for power at the device to become stable.
+	 */
+	async_usleep(100000);
+
+	/* enable port */
+	uhci_port_set_enabled(port, true);
+
+	/* The hub maintains the reset signal to that port for 10 ms
+	 * (See Section 11.5.1.5)
+	 */
+	{
+		usb_log_debug("Reset Signal start on port %d.\n",
+		    port->number);
+		port_status_t port_status =
+			port_status_read(port->address);
+		port_status |= STATUS_IN_RESET;
+		port_status_write(port->address, port_status);
+		async_usleep(10000);
+		port_status =
+			port_status_read(port->address);
+		port_status &= ~STATUS_IN_RESET;
+		port_status_write(port->address, port_status);
+		usb_log_debug("Reset Signal stop on port %d.\n",
+		    port->number);
+	}
+
+	/* assign address to device */
+	ret = usb_drv_req_set_address(port->hc_phone, 0, usb_address);
+
+	if (ret != EOK) { /* address assigning went wrong */
+		usb_log_error("Failed(%d) to assign address to the device.\n", ret);
+		uhci_port_set_enabled(port, false);
+		int release = usb_drv_release_default_address(port->hc_phone);
+		if (release != EOK) {
+			usb_log_error("Failed to release default address on port %d.\n",
+			    port->number);
+			return release;
+		}
+		usb_log_debug("Sucessfully released default address on port %d.\n",
+		    port->number);
+		return ret;
+	}
+	usb_log_debug("Sucessfully assigned address %d for port %d.\n",
+	    usb_address, port->number);
+
+	/* release default address */
+	ret = usb_drv_release_default_address(port->hc_phone);
+	if (ret != EOK) {
+		usb_log_error("Failed to release default address on port %d.\n",
+		    port->number);
+		return ret;
+	}
+	usb_log_debug("Sucessfully released default address on port %d.\n",
+	    port->number);
+
+	/* communicate and possibly report to devman */
+	assert(port->attached_device == 0);
+
+	ret = usb_drv_register_child_in_devman(port->hc_phone, port->rh,
+	  usb_address, &port->attached_device);
+
+	if (ret != EOK) { /* something went wrong */
+		usb_log_error("Failed(%d) in usb_drv_register_child.\n", ret);
+		uhci_port_set_enabled(port, false);
+		return ENOMEM;
+	}
+	usb_log_info("Sucessfully added device on port(%d) address(%d) handle %d.\n",
+		port->number, usb_address, port->attached_device);
+
+	ret =
+	  usb_drv_bind_address(port->hc_phone, usb_address, port->attached_device);
+	// TODO: proper error check here
+	assert(ret == EOK);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int uhci_port_remove_device(uhci_port_t *port)
+{
+	usb_log_error("Don't know how to remove device %#x.\n",
+		(unsigned int)port->attached_device);
+//	uhci_port_set_enabled(port, false);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
+{
+	assert(port);
+
+	/* read register value */
+	port_status_t port_status
+		= port_status_read(port->address);
+
+	/* enable port: register write */
+	if (enabled) {
+		port_status |= STATUS_ENABLED;
+	} else {
+		port_status &= ~STATUS_ENABLED;
+	}
+	port_status_write(port->address, port_status);
+
+	usb_log_info("%s port %d.\n",
+	  enabled ? "Enabled" : "Disabled", port->number);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/port.h
===================================================================
--- uspace/drv/uhci-rhd/port.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-rhd/port.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI port driver
+ */
+#ifndef DRV_UHCI_PORT_H
+#define DRV_UHCI_PORT_H
+
+#include <assert.h>
+#include <driver.h> /* device_t */
+#include <stdint.h>
+
+#include "port_status.h"
+
+typedef struct uhci_port
+{
+	port_status_t *address;
+	unsigned number;
+	unsigned wait_period_usec;
+	int hc_phone;
+	device_t *rh;
+	devman_handle_t attached_device;
+	fid_t checker;
+} uhci_port_t;
+
+int uhci_port_init(
+  uhci_port_t *port, port_status_t *address, unsigned number,
+  unsigned usec, device_t *rh, int parent_phone);
+
+void uhci_port_fini(uhci_port_t *port);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/port_status.c
===================================================================
--- uspace/drv/uhci-rhd/port_status.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-rhd/port_status.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <assert.h>
+#include <stdio.h>
+
+#include <usb/debug.h>
+
+#include "port_status.h"
+
+struct flag_name
+{
+	unsigned flag;
+	const char *name;
+};
+
+static const struct flag_name flags[] =
+{
+	{ STATUS_SUSPEND, "suspended" },
+	{ STATUS_IN_RESET, "in reset" },
+	{ STATUS_LOW_SPEED, "low speed device" },
+	{ STATUS_ALWAYS_ONE, "always 1 bit" },
+	{ STATUS_RESUME, "resume" },
+	{ STATUS_LINE_D_MINUS, "line D- value" },
+	{ STATUS_LINE_D_PLUS, "line D+ value" },
+	{ STATUS_ENABLED_CHANGED, "enabled changed" },
+	{ STATUS_ENABLED, "enabled" },
+	{ STATUS_CONNECTED_CHANGED, "connected changed" },
+	{ STATUS_CONNECTED, "connected" }
+};
+
+void print_port_status(port_status_t value)
+{
+	unsigned i = 0;
+	for (;i < sizeof(flags)/sizeof(struct flag_name); ++i) {
+		usb_log_debug2("\t%s status: %s.\n", flags[i].name,
+		  value & flags[i].flag ? "YES" : "NO");
+	}
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/port_status.h
===================================================================
--- uspace/drv/uhci-rhd/port_status.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-rhd/port_status.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_TD_PORT_STATUS_H
+#define DRV_UHCI_TD_PORT_STATUS_H
+
+#include <libarch/ddi.h> /* pio_read and pio_write */
+
+#include <stdint.h>
+
+typedef uint16_t port_status_t;
+
+enum {
+	STATUS_CONNECTED         = 1 << 0,
+	STATUS_CONNECTED_CHANGED = 1 << 1,
+	STATUS_ENABLED           = 1 << 2,
+	STATUS_ENABLED_CHANGED   = 1 << 3,
+	STATUS_LINE_D_PLUS       = 1 << 4,
+	STATUS_LINE_D_MINUS      = 1 << 5,
+	STATUS_RESUME            = 1 << 6,
+	STATUS_ALWAYS_ONE        = 1 << 7,
+
+	STATUS_LOW_SPEED = 1 <<  8,
+	STATUS_IN_RESET  = 1 <<  9,
+	STATUS_SUSPEND   = 1 << 12,
+};
+
+static inline port_status_t port_status_read(port_status_t * address)
+	{ return pio_read_16(address); }
+
+static inline void port_status_write(
+  port_status_t *address, port_status_t value)
+	{ pio_write_16(address, value); }
+
+void print_port_status(const port_status_t status);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/root_hub.c
===================================================================
--- uspace/drv/uhci-rhd/root_hub.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-rhd/root_hub.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <errno.h>
+#include <stdint.h>
+
+#include <usb/usbdrv.h>
+#include <usb/debug.h>
+
+#include "root_hub.h"
+
+
+int uhci_root_hub_init(
+  uhci_root_hub_t *instance, void *addr, size_t size, device_t *rh)
+{
+	assert(instance);
+	assert(rh);
+	int ret;
+	ret = usb_drv_find_hc(rh, &instance->hc_handle);
+	usb_log_info("rh found(%d) hc handle: %d.\n", ret, instance->hc_handle);
+	if (ret != EOK) {
+		return ret;
+	}
+
+	/* allow access to root hub registers */
+	assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT == size);
+	port_status_t *regs;
+	ret = pio_enable(
+	  addr, sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT, (void**)&regs);
+
+	if (ret < 0) {
+		usb_log_error("Failed to gain access to port registers at %p\n", regs);
+		return ret;
+	}
+
+	/* add fibrils for periodic port checks */
+	unsigned i = 0;
+	for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
+		/* connect to the parent device (HC) */
+		int parent_phone = devman_device_connect(instance->hc_handle, 0);
+		//usb_drv_hc_connect(rh, instance->hc_handle, 0);
+		if (parent_phone < 0) {
+			usb_log_error("Failed to connect to the HC device port %d.\n", i);
+			return parent_phone;
+		}
+		/* mind pointer arithmetics */
+		int ret = uhci_port_init(
+		  &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh, parent_phone);
+		if (ret != EOK) {
+			unsigned j = 0;
+			for (;j < i; ++j)
+				uhci_port_fini(&instance->ports[j]);
+			return ret;
+		}
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+int uhci_root_hub_fini( uhci_root_hub_t* instance )
+{
+	assert( instance );
+	// TODO:
+	//destroy fibril here
+	//disable access to registers
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/root_hub.h
===================================================================
--- uspace/drv/uhci-rhd/root_hub.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-rhd/root_hub.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2010 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_ROOT_HUB_H
+#define DRV_UHCI_ROOT_HUB_H
+
+#include <fibril.h>
+#include <driver.h> /* for device_t */
+
+#include "port.h"
+
+#define UHCI_ROOT_HUB_PORT_COUNT 2
+#define UHCI_ROOT_HUB_PORT_REGISTERS_OFFSET 0x10
+#define ROOT_HUB_WAIT_USEC 10000000 /* 10 seconds */
+
+typedef struct root_hub {
+	uhci_port_t ports[UHCI_ROOT_HUB_PORT_COUNT];
+	devman_handle_t hc_handle;
+} uhci_root_hub_t;
+
+int uhci_root_hub_init(
+  uhci_root_hub_t *instance, void *addr, size_t size, device_t *rh);
+
+int uhci_root_hub_fini(uhci_root_hub_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci-rhd/uhci-rhd.ma
===================================================================
--- uspace/drv/uhci-rhd/uhci-rhd.ma	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/drv/uhci-rhd/uhci-rhd.ma	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,1 @@
+10 usb&uhci&root-hub
Index: pace/drv/uhci/Makefile
===================================================================
--- uspace/drv/uhci/Makefile	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ 	(revision )
@@ -1,39 +1,0 @@
-#
-# Copyright (c) 2010 Vojtech Horky
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include
-BINARY = uhci
-
-SOURCES = \
-	main.c \
-	pci.c \
-	transfers.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/uhci/main.c
===================================================================
--- uspace/drv/uhci/main.c	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ 	(revision )
@@ -1,103 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <usb/hcdhubd.h>
-#include <usb_iface.h>
-#include <usb/debug.h>
-#include <errno.h>
-#include <str_error.h>
-#include <driver.h>
-#include "uhci.h"
-
-static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
-{
-	/* This shall be called only for the UHCI itself. */
-	assert(dev->parent == NULL);
-
-	*handle = dev->handle;
-	return EOK;
-}
-
-static usb_iface_t hc_usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle
-};
-
-static device_ops_t uhci_ops = {
-	.interfaces[USB_DEV_IFACE] = &hc_usb_iface,
-	.interfaces[USBHC_DEV_IFACE] = &uhci_iface
-};
-
-static int uhci_add_device(device_t *device)
-{
-	usb_dprintf(NAME, 1, "uhci_add_device() called\n");
-	device->ops = &uhci_ops;
-
-	uintptr_t io_reg_base;
-	size_t io_reg_size;
-	int irq;
-
-	int rc = pci_get_my_registers(device,
-	    &io_reg_base, &io_reg_size, &irq);
-
-	if (rc != EOK) {
-		fprintf(stderr,
-		    NAME ": failed to get I/O registers addresses: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-
-	usb_dprintf(NAME, 2, "I/O regs at 0x%X (size %zu), IRQ %d.\n",
-	    io_reg_base, io_reg_size, irq);
-
-	/*
-	 * We need to announce the presence of our root hub.
-	 */
-	usb_dprintf(NAME, 2, "adding root hub\n");
-	usb_hcd_add_root_hub(device);
-
-	return EOK;
-}
-
-static driver_ops_t uhci_driver_ops = {
-	.add_device = uhci_add_device,
-};
-
-static driver_t uhci_driver = {
-	.name = NAME,
-	.driver_ops = &uhci_driver_ops
-};
-
-int main(int argc, char *argv[])
-{
-	/*
-	 * Do some global initializations.
-	 */
-	sleep(5);
-	usb_dprintf_enable(NAME, 5);
-
-	return driver_main(&uhci_driver);
-}
Index: pace/drv/uhci/pci.c
===================================================================
--- uspace/drv/uhci/pci.c	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ 	(revision )
@@ -1,126 +1,0 @@
-/*
- * Copyright (c) 2011 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/**
- * @addtogroup drvusbuhci
- * @{
- */
-/**
- * @file
- * PCI related functions needed by the UHCI driver.
- */
-#include "uhci.h"
-#include <errno.h>
-#include <assert.h>
-#include <devman.h>
-#include <device/hw_res.h>
-
-/** Get address of registers and IRQ for given device.
- *
- * @param[in] dev Device asking for the addresses.
- * @param[out] io_reg_address Base address of the I/O range.
- * @param[out] io_reg_size Size of the I/O range.
- * @param[out] irq_no IRQ assigned to the device.
- * @return Error code.
- */
-int pci_get_my_registers(device_t *dev,
-    uintptr_t *io_reg_address, size_t *io_reg_size,
-    int *irq_no)
-{
-	assert(dev != NULL);
-
-	int parent_phone = devman_parent_device_connect(dev->handle,
-	    IPC_FLAG_BLOCKING);
-	if (parent_phone < 0) {
-		return parent_phone;
-	}
-
-	int rc;
-
-	hw_resource_list_t hw_resources;
-	rc = hw_res_get_resource_list(parent_phone, &hw_resources);
-	if (rc != EOK) {
-		goto leave;
-	}
-
-	uintptr_t io_address = 0;
-	size_t io_size = 0;
-	bool io_found = false;
-
-	int irq = 0;
-	bool irq_found = false;
-
-	size_t i;
-	for (i = 0; i < hw_resources.count; i++) {
-		hw_resource_t *res = &hw_resources.resources[i];
-		switch (res->type) {
-			case INTERRUPT:
-				irq = res->res.interrupt.irq;
-				irq_found = true;
-				break;
-			case IO_RANGE:
-				io_address = (uintptr_t)
-				    res->res.io_range.address;
-				io_size = res->res.io_range.size;
-				io_found = true;
-				break;
-			default:
-				break;
-		}
-	}
-
-	if (!io_found) {
-		rc = ENOENT;
-		goto leave;
-	}
-
-	if (!irq_found) {
-		rc = ENOENT;
-		goto leave;
-	}
-
-	if (io_reg_address != NULL) {
-		*io_reg_address = io_address;
-	}
-	if (io_reg_size != NULL) {
-		*io_reg_size = io_size;
-	}
-	if (irq_no != NULL) {
-		*irq_no = irq;
-	}
-
-	rc = EOK;
-leave:
-	ipc_hangup(parent_phone);
-
-	return rc;
-}
-
-/**
- * @}
- */
-
Index: pace/drv/uhci/transfers.c
===================================================================
--- uspace/drv/uhci/transfers.c	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ 	(revision )
@@ -1,160 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <usb/hcdhubd.h>
-#include <errno.h>
-
-#include "uhci.h"
-
-static int enqueue_transfer_out(device_t *dev,
-    usb_target_t target, usb_transfer_type_t transfer_type,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	printf(NAME ": transfer OUT [%d.%d (%s); %zu]\n",
-	    target.address, target.endpoint,
-	    usb_str_transfer_type(transfer_type),
-	    size);
-
-	return ENOTSUP;
-}
-
-static int enqueue_transfer_setup(device_t *dev,
-    usb_target_t target, usb_transfer_type_t transfer_type,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	printf(NAME ": transfer SETUP [%d.%d (%s); %zu]\n",
-	    target.address, target.endpoint,
-	    usb_str_transfer_type(transfer_type),
-	    size);
-
-	return ENOTSUP;
-}
-
-static int enqueue_transfer_in(device_t *dev,
-    usb_target_t target, usb_transfer_type_t transfer_type,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	printf(NAME ": transfer IN [%d.%d (%s); %zu]\n",
-	    target.address, target.endpoint,
-	    usb_str_transfer_type(transfer_type),
-	    size);
-
-	return ENOTSUP;
-}
-
-
-static int get_address(device_t *dev, devman_handle_t handle,
-    usb_address_t *address)
-{
-	return ENOTSUP;
-}
-
-static int interrupt_out(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return enqueue_transfer_out(dev, target, USB_TRANSFER_INTERRUPT,
-	    data, size,
-	    callback, arg);
-}
-
-static int interrupt_in(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return enqueue_transfer_in(dev, target, USB_TRANSFER_INTERRUPT,
-	    data, size,
-	    callback, arg);
-}
-
-static int control_write_setup(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
-	    data, size,
-	    callback, arg);
-}
-
-static int control_write_data(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
-	    data, size,
-	    callback, arg);
-}
-
-static int control_write_status(device_t *dev, usb_target_t target,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
-	    NULL, 0,
-	    callback, arg);
-}
-
-static int control_read_setup(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
-	    data, size,
-	    callback, arg);
-}
-
-static int control_read_data(device_t *dev, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
-	    data, size,
-	    callback, arg);
-}
-
-static int control_read_status(device_t *dev, usb_target_t target,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
-	    NULL, 0,
-	    callback, arg);
-}
-
-
-usbhc_iface_t uhci_iface = {
-	.tell_address = get_address,
-	.interrupt_out = interrupt_out,
-	.interrupt_in = interrupt_in,
-	.control_write_setup = control_write_setup,
-	.control_write_data = control_write_data,
-	.control_write_status = control_write_status,
-	.control_read_setup = control_read_setup,
-	.control_read_data = control_read_data,
-	.control_read_status = control_read_status
-};
Index: pace/drv/uhci/uhci.h
===================================================================
--- uspace/drv/uhci/uhci.h	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ 	(revision )
@@ -1,49 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbuhci
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef DRV_UHCI_UHCI_H
-#define DRV_UHCI_UHCI_H
-
-#include <usbhc_iface.h>
-
-#define NAME "uhci"
-
-usbhc_iface_t uhci_iface;
-
-int pci_get_my_registers(device_t *, uintptr_t *, size_t *, int *);
-
-#endif
-/**
- * @}
- */
Index: pace/drv/uhci/uhci.ma
===================================================================
--- uspace/drv/uhci/uhci.ma	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ 	(revision )
@@ -1,2 +1,0 @@
-10 pci/ven=8086&dev=7020
-
Index: uspace/drv/usbhid/main.c
===================================================================
--- uspace/drv/usbhid/main.c	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ uspace/drv/usbhid/main.c	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -56,5 +56,5 @@
 #include "layout.h"
 
-#define BUFFER_SIZE 32
+#define BUFFER_SIZE 8
 #define NAME "usbhid"
 
@@ -262,4 +262,5 @@
 }
 
+# if 0
 /*
  * Kbd functions
@@ -297,5 +298,4 @@
 	return EOK;
 }
-
 static int usbkbd_process_descriptors(usb_hid_dev_kbd_t *kbd_dev)
 {
@@ -363,5 +363,5 @@
 	return EOK;
 }
-
+#endif
 static usb_hid_dev_kbd_t *usbkbd_init_device(device_t *dev)
 {
@@ -404,6 +404,9 @@
 	 */
 
+
 	// TODO: get descriptors, parse descriptors and save endpoints
-	usbkbd_process_descriptors(kbd_dev);
+	//usbkbd_process_descriptors(kbd_dev);
+	usb_drv_req_set_configuration(
+	  kbd_dev->device->parent_phone, kbd_dev->address, 1);
 
 
@@ -467,5 +470,5 @@
 
 	while (true) {
-		async_usleep(1000 * 1000 * 2);
+		async_usleep(1000 * 10);
 
 		sess_rc = usb_endpoint_pipe_start_session(&kbd_dev->poll_pipe);
Index: uspace/lib/usb/include/usb/addrkeep.h
===================================================================
--- uspace/lib/usb/include/usb/addrkeep.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
+++ uspace/lib/usb/include/usb/addrkeep.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -0,0 +1,1 @@
+hcd.h
Index: uspace/lib/usb/include/usb/devreq.h
===================================================================
--- uspace/lib/usb/include/usb/devreq.h	(revision 458e40c6531f2d4b1b0caf31c3b0f364ffe73a06)
+++ uspace/lib/usb/include/usb/devreq.h	(revision 400575c58f6b62c46b8baaa757924a9033c50a83)
@@ -70,4 +70,5 @@
 	/** Main parameter to the request. */
 	union {
+		uint16_t value;
 		/* FIXME: add #ifdefs according to host endianess */
 		struct {
@@ -75,5 +76,4 @@
 			uint8_t value_high;
 		};
-		uint16_t value;
 	};
 	/** Auxiliary parameter to the request.
