Index: abi/include/ipc/methods.h
===================================================================
--- abi/include/ipc/methods.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ abi/include/ipc/methods.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -127,5 +127,8 @@
  *
  * on answer, the recipient must set:
- * - ARG1 - dst as_area base adress
+ *
+ * - ARG1 - dst as_area lower bound
+ * - ARG2 - dst as_area base adress pointer
+ *          (filled automatically by the kernel)
  *
  */
@@ -133,7 +136,6 @@
 
 /** Receive as_area over IPC.
- * - ARG1 - destination as_area base address
- * - ARG2 - destination as_area size
- * - ARG3 - user defined argument
+ * - ARG1 - destination as_area size
+ * - ARG2 - user defined argument
  *
  * on answer, the recipient must set:
@@ -141,4 +143,6 @@
  * - ARG1 - source as_area base address
  * - ARG2 - flags that will be used for sharing
+ * - ARG3 - dst as_area lower bound
+ * - ARG4 - dst as_area base address (filled automatically by kernel)
  *
  */
Index: abi/include/syscall.h
===================================================================
--- abi/include/syscall.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ abi/include/syscall.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -60,5 +60,4 @@
 	SYS_AS_AREA_CHANGE_FLAGS,
 	SYS_AS_AREA_DESTROY,
-	SYS_AS_GET_UNMAPPED_AREA,
 	
 	SYS_PAGE_FIND_MAPPING,
@@ -85,9 +84,11 @@
 	SYS_DEVICE_ASSIGN_DEVNO,
 	SYS_PHYSMEM_MAP,
+	SYS_PHYSMEM_UNMAP,
 	SYS_DMAMEM_MAP,
 	SYS_DMAMEM_UNMAP,
 	SYS_IOSPACE_ENABLE,
-	SYS_REGISTER_IRQ,
-	SYS_UNREGISTER_IRQ,
+	SYS_IOSPACE_DISABLE,
+	SYS_IRQ_REGISTER,
+	SYS_IRQ_UNREGISTER,
 	
 	SYS_SYSINFO_GET_VAL_TYPE,
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ boot/Makefile.common	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -124,5 +124,6 @@
 	nic/lo \
 	nic/ne2k \
-	nic/e1k
+	nic/e1k \
+	nic/rtl8139
 
 RD_DRV_CFG =
Index: contrib/conf/net-qe.sh
===================================================================
--- contrib/conf/net-qe.sh	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ contrib/conf/net-qe.sh	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -10,5 +10,9 @@
 		qemu $@ -device e1000,vlan=0 -net user -boot d -redir udp:8080::8080 -redir udp:8081::8081 -redir tcp:8080::8080 -redir tcp:8081::8081 -cdrom image.iso
 		;;
+	rtl8139)
+		shift
+		qemu $@ -device rtl8139,vlan=0 -net user -boot d -redir udp:8080::8080 -redir udp:8081::8081 -redir tcp:8080::8080 -redir tcp:8081::8081 -cdrom image.iso
+		;;
 	*)
-		echo "Usage: $0 {ne2k|e1k}"
+		echo "Usage: $0 {ne2k|e1k|rtl8139}"
 esac
Index: kernel/generic/include/ddi/ddi.h
===================================================================
--- kernel/generic/include/ddi/ddi.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ kernel/generic/include/ddi/ddi.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -55,11 +55,14 @@
 extern void ddi_parea_register(parea_t *);
 
-extern sysarg_t sys_physmem_map(uintptr_t, uintptr_t, size_t, unsigned int);
+extern sysarg_t sys_physmem_map(uintptr_t, size_t, unsigned int, void *,
+    uintptr_t);
+extern sysarg_t sys_physmem_unmap(uintptr_t);
 
-extern sysarg_t sys_dmamem_map(uintptr_t, size_t, unsigned int, unsigned int,
-    void *);
+extern sysarg_t sys_dmamem_map(size_t, unsigned int, unsigned int, void *,
+    void *, uintptr_t);
 extern sysarg_t sys_dmamem_unmap(uintptr_t, size_t, unsigned int);
 
 extern sysarg_t sys_iospace_enable(ddi_ioarg_t *);
+extern sysarg_t sys_iospace_disable(ddi_ioarg_t *);
 
 /*
Index: kernel/generic/include/ipc/sysipc.h
===================================================================
--- kernel/generic/include/ipc/sysipc.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ kernel/generic/include/ipc/sysipc.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -56,6 +56,6 @@
     unsigned int);
 extern sysarg_t sys_ipc_hangup(sysarg_t);
-extern sysarg_t sys_register_irq(inr_t, devno_t, sysarg_t, irq_code_t *);
-extern sysarg_t sys_unregister_irq(inr_t, devno_t);
+extern sysarg_t sys_irq_register(inr_t, devno_t, sysarg_t, irq_code_t *);
+extern sysarg_t sys_irq_unregister(inr_t, devno_t);
 
 #ifdef __32_BITS__
Index: kernel/generic/include/mm/as.h
===================================================================
--- kernel/generic/include/mm/as.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ kernel/generic/include/mm/as.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -242,10 +242,10 @@
 extern int as_page_fault(uintptr_t, pf_access_t, istate_t *);
 
-extern as_area_t *as_area_create(as_t *, unsigned int, size_t, uintptr_t,
-    unsigned int, mem_backend_t *, mem_backend_data_t *);
+extern as_area_t *as_area_create(as_t *, unsigned int, size_t, unsigned int,
+    mem_backend_t *, mem_backend_data_t *, uintptr_t *, uintptr_t);
 extern int as_area_destroy(as_t *, uintptr_t);
 extern int as_area_resize(as_t *, uintptr_t, size_t, unsigned int);
-extern int as_area_share(as_t *, uintptr_t, size_t, as_t *, uintptr_t,
-    unsigned int);
+extern int as_area_share(as_t *, uintptr_t, size_t, as_t *, unsigned int,
+    uintptr_t *, uintptr_t);
 extern int as_area_change_flags(as_t *, unsigned int, uintptr_t);
 
@@ -284,9 +284,8 @@
 
 /* Address space area related syscalls. */
-extern sysarg_t sys_as_area_create(uintptr_t, size_t, unsigned int);
+extern sysarg_t sys_as_area_create(uintptr_t, size_t, unsigned int, uintptr_t);
 extern sysarg_t sys_as_area_resize(uintptr_t, size_t, unsigned int);
 extern sysarg_t sys_as_area_change_flags(uintptr_t, unsigned int);
 extern sysarg_t sys_as_area_destroy(uintptr_t);
-extern sysarg_t sys_as_get_unmapped_area(uintptr_t, size_t);
 
 /* Introspection functions. */
Index: kernel/generic/src/ddi/ddi.c
===================================================================
--- kernel/generic/src/ddi/ddi.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ kernel/generic/src/ddi/ddi.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -90,11 +90,12 @@
  *
  * @param phys  Physical address of the starting frame.
- * @param virt  Virtual address of the starting page.
  * @param pages Number of pages to map.
  * @param flags Address space area flags for the mapping.
+ * @param virt  Virtual address of the starting page.
+ * @param bound Lowest virtual address bound.
  *
  * @return EOK on success.
  * @return EPERM if the caller lacks capabilities to use this syscall.
- * @return EBADMEM if phys or virt is not page aligned.
+ * @return EBADMEM if phys is not page aligned.
  * @return ENOENT if there is no task matching the specified ID or
  *         the physical address space is not enabled for mapping.
@@ -102,13 +103,10 @@
  *
  */
-NO_TRACE static int ddi_physmem_map(uintptr_t phys, uintptr_t virt, size_t pages,
-    unsigned int flags)
+NO_TRACE static int physmem_map(uintptr_t phys, size_t pages,
+    unsigned int flags, uintptr_t *virt, uintptr_t bound)
 {
 	ASSERT(TASK);
 	
 	if ((phys % FRAME_SIZE) != 0)
-		return EBADMEM;
-	
-	if ((virt % PAGE_SIZE) != 0)
 		return EBADMEM;
 	
@@ -185,6 +183,6 @@
 	
 map:
-	if (!as_area_create(TASK->as, flags, FRAMES2SIZE(pages), virt,
-	    AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) {
+	if (!as_area_create(TASK->as, flags, FRAMES2SIZE(pages),
+	    AS_AREA_ATTR_NONE, &phys_backend, &backend_data, virt, bound)) {
 		/*
 		 * The address space area was not created.
@@ -210,4 +208,44 @@
 }
 
+NO_TRACE static int physmem_unmap(uintptr_t virt)
+{
+	// TODO: implement unmap
+	return EOK;
+}
+
+/** Wrapper for SYS_PHYSMEM_MAP syscall.
+ *
+ * @param phys     Physical base address to map
+ * @param pages    Number of pages
+ * @param flags    Flags of newly mapped pages
+ * @param virt_ptr Destination virtual address
+ * @param bound    Lowest virtual address bound.
+ *
+ * @return 0 on success, otherwise it returns error code found in errno.h
+ *
+ */
+sysarg_t sys_physmem_map(uintptr_t phys, size_t pages, unsigned int flags,
+    void *virt_ptr, uintptr_t bound)
+{
+	uintptr_t virt = (uintptr_t) -1;
+	int rc = physmem_map(ALIGN_DOWN(phys, FRAME_SIZE), pages, flags,
+	    &virt, bound);
+	if (rc != EOK)
+		return rc;
+	
+	rc = copy_to_uspace(virt_ptr, &virt, sizeof(virt));
+	if (rc != EOK) {
+		physmem_unmap((uintptr_t) virt);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+sysarg_t sys_physmem_unmap(uintptr_t virt)
+{
+	return physmem_unmap(virt);
+}
+
 /** Enable range of I/O space for task.
  *
@@ -220,6 +258,5 @@
  *
  */
-NO_TRACE static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr,
-    size_t size)
+NO_TRACE static int iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size)
 {
 	/*
@@ -246,28 +283,8 @@
 	/* Lock the task and release the lock protecting tasks_btree. */
 	irq_spinlock_exchange(&tasks_lock, &task->lock);
-	
 	int rc = ddi_iospace_enable_arch(task, ioaddr, size);
-	
 	irq_spinlock_unlock(&task->lock, true);
 	
 	return rc;
-}
-
-/** Wrapper for SYS_PHYSMEM_MAP syscall.
- *
- * @param phys  Physical base address to map
- * @param virt  Destination virtual address
- * @param pages Number of pages
- * @param flags Flags of newly mapped pages
- *
- * @return 0 on success, otherwise it returns error code found in errno.h
- *
- */
-sysarg_t sys_physmem_map(uintptr_t phys, uintptr_t virt,
-    size_t pages, unsigned int flags)
-{
-	return (sysarg_t)
-	    ddi_physmem_map(ALIGN_DOWN(phys, FRAME_SIZE),
-	    ALIGN_DOWN(virt, PAGE_SIZE), pages, flags);
 }
 
@@ -286,68 +303,109 @@
 		return (sysarg_t) rc;
 	
-	return (sysarg_t) ddi_iospace_enable((task_id_t) arg.task_id,
+	return (sysarg_t) iospace_enable((task_id_t) arg.task_id,
 	    (uintptr_t) arg.ioaddr, (size_t) arg.size);
 }
 
-NO_TRACE static int dmamem_map(uintptr_t virt, size_t size,
-    unsigned int map_flags, unsigned int flags, void **phys)
+sysarg_t sys_iospace_disable(ddi_ioarg_t *uspace_io_arg)
+{
+	// TODO: implement
+	return ENOTSUP;
+}
+
+NO_TRACE static int dmamem_map(uintptr_t virt, size_t size, unsigned int map_flags,
+    unsigned int flags, void **phys)
 {
 	ASSERT(TASK);
 	
+	// TODO: implement locking of non-anonymous mapping
+	return page_find_mapping(virt, phys);
+}
+
+NO_TRACE static int dmamem_map_anonymous(size_t size, unsigned int map_flags,
+    unsigned int flags, void **phys, uintptr_t *virt, uintptr_t bound)
+{
+	ASSERT(TASK);
+	
+	size_t pages = SIZE2FRAMES(size);
+	uint8_t order;
+	
+	/* We need the 2^order >= pages */
+	if (pages == 1)
+		order = 0;
+	else
+		order = fnzb(pages - 1) + 1;
+	
+	*phys = frame_alloc_noreserve(order, 0);
+	if (*phys == NULL)
+		return ENOMEM;
+	
+	mem_backend_data_t backend_data;
+	backend_data.base = (uintptr_t) *phys;
+	backend_data.frames = pages;
+	
+	if (!as_area_create(TASK->as, map_flags, size,
+	    AS_AREA_ATTR_NONE, &phys_backend, &backend_data, virt, bound)) {
+		frame_free_noreserve((uintptr_t) *phys);
+		return ENOMEM;
+	}
+	
+	return EOK;
+}
+
+NO_TRACE static int dmamem_unmap(uintptr_t virt, size_t size)
+{
+	// TODO: implement unlocking & unmap
+	return EOK;
+}
+
+NO_TRACE static int dmamem_unmap_anonymous(uintptr_t virt)
+{
+	// TODO: implement unlocking & unmap
+	return EOK;
+}
+
+sysarg_t sys_dmamem_map(size_t size, unsigned int map_flags, unsigned int flags,
+    void *phys_ptr, void *virt_ptr, uintptr_t bound)
+{
 	if ((flags & DMAMEM_FLAGS_ANONYMOUS) == 0) {
-		// TODO: implement locking of non-anonymous mapping
-		return page_find_mapping(virt, phys);
+		/*
+		 * Non-anonymous DMA mapping
+		 */
+		
+		void *phys;
+		int rc = dmamem_map((uintptr_t) virt_ptr, size, map_flags,
+		    flags, &phys);
+		
+		if (rc != EOK)
+			return rc;
+		
+		rc = copy_to_uspace(phys_ptr, &phys, sizeof(phys));
+		if (rc != EOK) {
+			dmamem_unmap((uintptr_t) virt_ptr, size);
+			return rc;
+		}
 	} else {
-		// TODO: implement locking
-		
-		if ((virt % PAGE_SIZE) != 0)
-			return EBADMEM;
-		
-		size_t pages = SIZE2FRAMES(size);
-		uint8_t order;
-		
-		/* We need the 2^order >= pages */
-		if (pages == 1)
-			order = 0;
-		else
-			order = fnzb(pages - 1) + 1;
-		
-		*phys = frame_alloc_noreserve(order, 0);
-		if (*phys == NULL)
-			return ENOMEM;
-		
-		mem_backend_data_t backend_data;
-		backend_data.base = (uintptr_t) *phys;
-		backend_data.frames = pages;
-		
-		if (!as_area_create(TASK->as, map_flags, size, virt,
-		    AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) {
-			frame_free_noreserve((uintptr_t) *phys);
-			return ENOMEM;
+		/*
+		 * Anonymous DMA mapping
+		 */
+		
+		void *phys;
+		uintptr_t virt = (uintptr_t) -1;
+		int rc = dmamem_map_anonymous(size, map_flags, flags,
+		    &phys, &virt, bound);
+		if (rc != EOK)
+			return rc;
+		
+		rc = copy_to_uspace(phys_ptr, &phys, sizeof(phys));
+		if (rc != EOK) {
+			dmamem_unmap_anonymous((uintptr_t) virt);
+			return rc;
 		}
 		
-		return EOK;
-	}
-}
-
-NO_TRACE static int dmamem_unmap(uintptr_t virt, size_t size,
-    unsigned int flags)
-{
-	// TODO: implement unlocking & unmap
-	return EOK;
-}
-
-sysarg_t sys_dmamem_map(uintptr_t virt, size_t size, unsigned int map_flags,
-    unsigned int flags, void *phys_ptr)
-{
-	void *phys;
-	int rc = dmamem_map(virt, size, map_flags, flags, &phys);
-	if (rc != EOK)
-		return rc;
-	
-	rc = copy_to_uspace(phys_ptr, &phys, sizeof(phys));
-	if (rc != EOK) {
-		dmamem_unmap(virt, size, flags);
-		return rc;
+		rc = copy_to_uspace(virt_ptr, &virt, sizeof(virt));
+		if (rc != EOK) {
+			dmamem_unmap_anonymous((uintptr_t) virt);
+			return rc;
+		}
 	}
 	
@@ -357,5 +415,8 @@
 sysarg_t sys_dmamem_unmap(uintptr_t virt, size_t size, unsigned int flags)
 {
-	return dmamem_unmap(virt, size, flags);
+	if ((flags & DMAMEM_FLAGS_ANONYMOUS) == 0)
+		return dmamem_unmap(virt, size);
+	else
+		return dmamem_unmap_anonymous(virt);
 }
 
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ kernel/generic/src/ipc/irq.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -42,6 +42,6 @@
  *
  * The structure of a notification message is as follows:
- * - IMETHOD: interface and method as registered by the SYS_REGISTER_IRQ
- *            syscall
+ * - IMETHOD: interface and method as registered by
+ *            the SYS_IRQ_REGISTER syscall
  * - ARG1: payload modified by a 'top-half' handler
  * - ARG2: payload modified by a 'top-half' handler
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ kernel/generic/src/ipc/sysipc.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -271,7 +271,13 @@
 			irq_spinlock_unlock(&answer->sender->lock, true);
 			
+			uintptr_t dst_base = (uintptr_t) -1;
 			int rc = as_area_share(as, IPC_GET_ARG1(*olddata),
-			    IPC_GET_ARG2(*olddata), AS,
-			    IPC_GET_ARG1(answer->data), IPC_GET_ARG3(*olddata));
+			    IPC_GET_ARG2(*olddata), AS, IPC_GET_ARG3(*olddata),
+			    &dst_base, IPC_GET_ARG1(answer->data));
+			
+			if (rc == EOK)
+				rc = copy_to_uspace((void *) IPC_GET_ARG2(answer->data),
+				    &dst_base, sizeof(dst_base));
+			
 			IPC_SET_RETVAL(answer->data, rc);
 			return rc;
@@ -283,7 +289,9 @@
 			irq_spinlock_unlock(&answer->sender->lock, true);
 			
+			uintptr_t dst_base = (uintptr_t) -1;
 			int rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
-			    IPC_GET_ARG2(*olddata), as, IPC_GET_ARG1(*olddata),
-			    IPC_GET_ARG2(answer->data));
+			    IPC_GET_ARG1(*olddata), as, IPC_GET_ARG2(answer->data),
+			    &dst_base, IPC_GET_ARG3(answer->data));
+			IPC_SET_ARG4(answer->data, dst_base);
 			IPC_SET_RETVAL(answer->data, rc);
 		}
@@ -1185,5 +1193,5 @@
  *
  */
-sysarg_t sys_register_irq(inr_t inr, devno_t devno, sysarg_t imethod,
+sysarg_t sys_irq_register(inr_t inr, devno_t devno, sysarg_t imethod,
     irq_code_t *ucode)
 {
@@ -1202,5 +1210,5 @@
  *
  */
-sysarg_t sys_unregister_irq(inr_t inr, devno_t devno)
+sysarg_t sys_irq_unregister(inr_t inr, devno_t devno)
 {
 	if (!(cap_get(TASK) & CAP_IRQ_REG))
Index: kernel/generic/src/lib/elf.c
===================================================================
--- kernel/generic/src/lib/elf.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ kernel/generic/src/lib/elf.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -226,6 +226,6 @@
 	size_t mem_sz = entry->p_memsz + (entry->p_vaddr - base);
 	
-	as_area_t *area = as_area_create(as, flags, mem_sz, base,
-	    AS_AREA_ATTR_NONE, &elf_backend, &backend_data);
+	as_area_t *area = as_area_create(as, flags, mem_sz,
+	    AS_AREA_ATTR_NONE, &elf_backend, &backend_data, &base, 0);
 	if (!area)
 		return EE_MEMORY;
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ kernel/generic/src/mm/as.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -387,4 +387,71 @@
 }
 
+/** Return pointer to unmapped address space area
+ *
+ * The address space must be already locked when calling
+ * this function.
+ *
+ * @param as    Address space.
+ * @param bound Lowest address bound.
+ * @param size  Requested size of the allocation.
+ *
+ * @return Address of the beginning of unmapped address space area.
+ * @return -1 if no suitable address space area was found.
+ *
+ */
+NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound,
+    size_t size)
+{
+	ASSERT(mutex_locked(&as->lock));
+	
+	if (size == 0)
+		return (uintptr_t) -1;
+	
+	/*
+	 * Make sure we allocate from page-aligned
+	 * address. Check for possible overflow in
+	 * each step.
+	 */
+	
+	size_t pages = SIZE2FRAMES(size);
+	
+	/*
+	 * Find the lowest unmapped address aligned on the size
+	 * boundary, not smaller than bound and of the required size.
+	 */
+	
+	/* First check the bound address itself */
+	uintptr_t addr = ALIGN_UP(bound, PAGE_SIZE);
+	if ((addr >= bound) &&
+	    (check_area_conflicts(as, addr, pages, NULL)))
+		return addr;
+	
+	/* Eventually check the addresses behind each area */
+	list_foreach(as->as_area_btree.leaf_list, cur) {
+		btree_node_t *node =
+		    list_get_instance(cur, btree_node_t, leaf_link);
+		
+		for (btree_key_t i = 0; i < node->keys; i++) {
+			as_area_t *area = (as_area_t *) node->value[i];
+			
+			mutex_lock(&area->lock);
+			
+			addr =
+			    ALIGN_UP(area->base + P2SZ(area->pages), PAGE_SIZE);
+			bool avail =
+			    ((addr >= bound) && (addr >= area->base) &&
+			    (check_area_conflicts(as, addr, pages, area)));
+			
+			mutex_unlock(&area->lock);
+			
+			if (avail)
+				return addr;
+		}
+	}
+	
+	/* No suitable address space area found */
+	return (uintptr_t) -1;
+}
+
 /** Create address space area of common attributes.
  *
@@ -394,8 +461,11 @@
  * @param flags        Flags of the area memory.
  * @param size         Size of area.
- * @param base         Base address of area.
  * @param attrs        Attributes of the area.
  * @param backend      Address space area backend. NULL if no backend is used.
  * @param backend_data NULL or a pointer to an array holding two void *.
+ * @param base         Starting virtual address of the area.
+ *                     If set to -1, a suitable mappable area is found.
+ * @param bound        Lowest address bound if base is set to -1.
+ *                     Otherwise ignored.
  *
  * @return Address space area on success or NULL on failure.
@@ -403,8 +473,8 @@
  */
 as_area_t *as_area_create(as_t *as, unsigned int flags, size_t size,
-    uintptr_t base, unsigned int attrs, mem_backend_t *backend,
-    mem_backend_data_t *backend_data)
-{
-	if ((base % PAGE_SIZE) != 0)
+    unsigned int attrs, mem_backend_t *backend,
+    mem_backend_data_t *backend_data, uintptr_t *base, uintptr_t bound)
+{
+	if ((*base != (uintptr_t) -1) && ((*base % PAGE_SIZE) != 0))
 		return NULL;
 	
@@ -420,5 +490,13 @@
 	mutex_lock(&as->lock);
 	
-	if (!check_area_conflicts(as, base, pages, NULL)) {
+	if (*base == (uintptr_t) -1) {
+		*base = as_get_unmapped_area(as, bound, size);
+		if (*base == (uintptr_t) -1) {
+			mutex_unlock(&as->lock);
+			return NULL;
+		}
+	}
+	
+	if (!check_area_conflicts(as, *base, pages, NULL)) {
 		mutex_unlock(&as->lock);
 		return NULL;
@@ -434,5 +512,5 @@
 	area->pages = pages;
 	area->resident = 0;
-	area->base = base;
+	area->base = *base;
 	area->sh_info = NULL;
 	area->backend = backend;
@@ -452,5 +530,6 @@
 	
 	btree_create(&area->used_space);
-	btree_insert(&as->as_area_btree, base, (void *) area, NULL);
+	btree_insert(&as->as_area_btree, *base, (void *) area,
+	    NULL);
 	
 	mutex_unlock(&as->lock);
@@ -860,6 +939,9 @@
  * @param acc_size       Expected size of the source area.
  * @param dst_as         Pointer to destination address space.
- * @param dst_base       Target base address.
  * @param dst_flags_mask Destination address space area flags mask.
+ * @param dst_base       Target base address. If set to -1,
+ *                       a suitable mappable area is found.
+ * @param bound          Lowest address bound if dst_base is set to -1.
+ *                       Otherwise ignored.
  *
  * @return Zero on success.
@@ -873,5 +955,6 @@
  */
 int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
-    as_t *dst_as, uintptr_t dst_base, unsigned int dst_flags_mask)
+    as_t *dst_as, unsigned int dst_flags_mask, uintptr_t *dst_base,
+    uintptr_t bound)
 {
 	mutex_lock(&src_as->lock);
@@ -945,6 +1028,7 @@
 	 * to support sharing in less privileged mode.
 	 */
-	as_area_t *dst_area = as_area_create(dst_as, dst_flags_mask, src_size,
-	    dst_base, AS_AREA_ATTR_PARTIAL, src_backend, &src_backend_data);
+	as_area_t *dst_area = as_area_create(dst_as, dst_flags_mask,
+	    src_size, AS_AREA_ATTR_PARTIAL, src_backend,
+	    &src_backend_data, dst_base, bound);
 	if (!dst_area) {
 		/*
@@ -1955,15 +2039,16 @@
  */
 
-/** Wrapper for as_area_create(). */
-sysarg_t sys_as_area_create(uintptr_t address, size_t size, unsigned int flags)
-{
-	if (as_area_create(AS, flags | AS_AREA_CACHEABLE, size, address,
-	    AS_AREA_ATTR_NONE, &anon_backend, NULL))
-		return (sysarg_t) address;
-	else
+sysarg_t sys_as_area_create(uintptr_t base, size_t size, unsigned int flags,
+    uintptr_t bound)
+{
+	uintptr_t virt = base;
+	as_area_t *area = as_area_create(AS, flags | AS_AREA_CACHEABLE, size,
+	    AS_AREA_ATTR_NONE, &anon_backend, NULL, &virt, bound);
+	if (area == NULL)
 		return (sysarg_t) -1;
-}
-
-/** Wrapper for as_area_resize(). */
+	
+	return (sysarg_t) virt;
+}
+
 sysarg_t sys_as_area_resize(uintptr_t address, size_t size, unsigned int flags)
 {
@@ -1971,5 +2056,4 @@
 }
 
-/** Wrapper for as_area_change_flags(). */
 sysarg_t sys_as_area_change_flags(uintptr_t address, unsigned int flags)
 {
@@ -1977,75 +2061,7 @@
 }
 
-/** Wrapper for as_area_destroy(). */
 sysarg_t sys_as_area_destroy(uintptr_t address)
 {
 	return (sysarg_t) as_area_destroy(AS, address);
-}
-
-/** Return pointer to unmapped address space area
- *
- * @param base Lowest address bound.
- * @param size Requested size of the allocation.
- *
- * @return Pointer to the beginning of unmapped address space area.
- *
- */
-sysarg_t sys_as_get_unmapped_area(uintptr_t base, size_t size)
-{
-	if (size == 0)
-		return 0;
-	
-	/*
-	 * Make sure we allocate from page-aligned
-	 * address. Check for possible overflow in
-	 * each step.
-	 */
-	
-	size_t pages = SIZE2FRAMES(size);
-	uintptr_t ret = 0;
-	
-	/*
-	 * Find the lowest unmapped address aligned on the sz
-	 * boundary, not smaller than base and of the required size.
-	 */
-	
-	mutex_lock(&AS->lock);
-	
-	/* First check the base address itself */
-	uintptr_t addr = ALIGN_UP(base, PAGE_SIZE);
-	if ((addr >= base) &&
-	    (check_area_conflicts(AS, addr, pages, NULL)))
-		ret = addr;
-	
-	/* Eventually check the addresses behind each area */
-	list_foreach(AS->as_area_btree.leaf_list, cur) {
-		if (ret != 0)
-			break;
-
-		btree_node_t *node =
-		    list_get_instance(cur, btree_node_t, leaf_link);
-		
-		btree_key_t i;
-		for (i = 0; (ret == 0) && (i < node->keys); i++) {
-			uintptr_t addr;
-
-			as_area_t *area = (as_area_t *) node->value[i];
-			
-			mutex_lock(&area->lock);
-			
-			addr = ALIGN_UP(area->base + P2SZ(area->pages),
-			    PAGE_SIZE);
-			
-			if ((addr >= base) && (addr >= area->base) &&
-			    (check_area_conflicts(AS, addr, pages, area)))
-				ret = addr;
-			
-			mutex_unlock(&area->lock);
-		}
-	}
-	
-	mutex_unlock(&AS->lock);
-	
-	return (sysarg_t) ret;
 }
 
Index: kernel/generic/src/proc/program.c
===================================================================
--- kernel/generic/src/proc/program.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ kernel/generic/src/proc/program.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -87,8 +87,8 @@
 	 * Create the stack address space area.
 	 */
+	uintptr_t virt = USTACK_ADDRESS;
 	as_area_t *area = as_area_create(as,
 	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
-	    STACK_SIZE, USTACK_ADDRESS, AS_AREA_ATTR_NONE,
-	    &anon_backend, NULL);
+	    STACK_SIZE, AS_AREA_ATTR_NONE, &anon_backend, NULL, &virt, 0);
 	if (!area)
 		return ENOMEM;
Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ kernel/generic/src/syscall/syscall.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -146,5 +146,4 @@
 	(syshandler_t) sys_as_area_change_flags,
 	(syshandler_t) sys_as_area_destroy,
-	(syshandler_t) sys_as_get_unmapped_area,
 	
 	/* Page mapping related syscalls. */
@@ -176,9 +175,11 @@
 	(syshandler_t) sys_device_assign_devno,
 	(syshandler_t) sys_physmem_map,
+	(syshandler_t) sys_physmem_unmap,
 	(syshandler_t) sys_dmamem_map,
 	(syshandler_t) sys_dmamem_unmap,
 	(syshandler_t) sys_iospace_enable,
-	(syshandler_t) sys_register_irq,
-	(syshandler_t) sys_unregister_irq,
+	(syshandler_t) sys_iospace_disable,
+	(syshandler_t) sys_irq_register,
+	(syshandler_t) sys_irq_unregister,
 	
 	/* Sysinfo syscalls. */
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/Makefile	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -120,5 +120,6 @@
 	drv/nic/lo \
 	drv/nic/ne2k \
-	drv/nic/e1k
+	drv/nic/e1k \
+	drv/nic/rtl8139
 
 ifeq ($(CONFIG_PCC),y)
Index: uspace/app/klog/klog.c
===================================================================
--- uspace/app/klog/klog.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/app/klog/klog.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -205,13 +205,6 @@
 	klog_length = size / sizeof(wchar_t);
 	
-	klog = (wchar_t *) as_get_mappable_page(size);
-	if (klog == NULL) {
-		fprintf(stderr, "%s: Unable to allocate virtual memory area\n",
-		    NAME);
-		return ENOMEM;
-	}
-	
-	rc = physmem_map((void *) faddr, (void *) klog, pages,
-	    AS_AREA_READ | AS_AREA_CACHEABLE);
+	rc = physmem_map((void *) faddr, pages,
+	    AS_AREA_READ | AS_AREA_CACHEABLE, (void *) &klog);
 	if (rc != EOK) {
 		fprintf(stderr, "%s: Unable to map klog\n", NAME);
Index: uspace/app/mkbd/main.c
===================================================================
--- uspace/app/mkbd/main.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/app/mkbd/main.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -48,4 +48,5 @@
 #include <usb/dev/pipes.h>
 #include <async.h>
+#include <usb/dev.h>
 #include <usb/hid/usages/core.h>
 #include <usb/hid/hidparser.h>
Index: uspace/app/tester/mm/common.c
===================================================================
--- uspace/app/tester/mm/common.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/app/tester/mm/common.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -342,16 +342,9 @@
 	link_initialize(&area->link);
 	
-	/* Map the memory area */
-	void *addr = as_get_mappable_page(size);
-	if (addr == NULL) {
+	area->addr = as_area_create((void *) -1, size,
+	    AS_AREA_WRITE | AS_AREA_READ);
+	if (area->addr == (void *) -1) {
 		free(area);
 		check_consistency("map_area (a)");
-		return NULL;
-	}
-	
-	area->addr = as_area_create(addr, size, AS_AREA_WRITE | AS_AREA_READ);
-	if (area->addr == (void *) -1) {
-		free(area);
-		check_consistency("map_area (b)");
 		return NULL;
 	}
Index: uspace/app/tester/mm/mapping1.c
===================================================================
--- uspace/app/tester/mm/mapping1.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/app/tester/mm/mapping1.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -35,15 +35,16 @@
 #include "../tester.h"
 
-#define BUFFER1_PAGES 4
-#define BUFFER2_PAGES 2
+#define BUFFER1_PAGES  4
+#define BUFFER2_PAGES  2
 
 static void *create_as_area(size_t size)
 {
-	void *result = as_get_mappable_page(size);
 	TPRINTF("Creating AS area...\n");
-	if (as_area_create(result, size,
-	    AS_AREA_READ | AS_AREA_WRITE) != result) {
+	
+	void *result = as_area_create((void *) -1, size,
+	    AS_AREA_READ | AS_AREA_WRITE);
+	if (result == (void *) -1)
 		return NULL;
-	}
+	
 	return result;
 }
Index: uspace/app/trace/syscalls.c
===================================================================
--- uspace/app/trace/syscalls.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/app/trace/syscalls.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -72,6 +72,6 @@
     [SYS_PHYSMEM_MAP] = { "physmem_map",		4,	V_ERRNO },
     [SYS_IOSPACE_ENABLE] = { "iospace_enable",		1,	V_ERRNO },
-    [SYS_REGISTER_IRQ] = { "register_irq",	4,	V_ERRNO },
-    [SYS_UNREGISTER_IRQ] = { "unregister_irq",	2,	V_ERRNO },
+    [SYS_IRQ_REGISTER] = { "irq_register",	4,	V_ERRNO },
+    [SYS_IRQ_UNREGISTER] = { "irq_unregister",	2,	V_ERRNO },
 
     [SYS_SYSINFO_GET_VAL_TYPE] = { "sysinfo_get_val_type",		2,	V_INTEGER },
Index: uspace/app/usbinfo/dev.c
===================================================================
--- uspace/app/usbinfo/dev.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/app/usbinfo/dev.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -34,5 +34,6 @@
  * Representation of queried device.
  */
-#include <usb/dev/pipes.h>
+#include <usb/dev.h>
+#include <usb/hc.h>
 #include <errno.h>
 #include <str_error.h>
@@ -52,5 +53,8 @@
 	bool transfer_started = false;
 
-	rc = usb_device_connection_initialize(&dev->wire, hc_handle, dev_addr);
+	usb_hc_connection_initialize(&dev->hc_conn, hc_handle);
+
+	rc = usb_device_connection_initialize(
+	    &dev->wire, &dev->hc_conn, dev_addr);
 	if (rc != EOK) {
 		fprintf(stderr,
Index: uspace/app/usbinfo/info.c
===================================================================
--- uspace/app/usbinfo/info.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/app/usbinfo/info.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -287,4 +287,19 @@
 void dump_strings(usbinfo_device_t *dev)
 {
+	/* Find used indexes. Devices with more than 64 strings are very rare.*/
+	uint64_t str_mask = 0;
+	find_string_indexes_callback((uint8_t *)&dev->device_descriptor, 0,
+	    &str_mask);
+	usb_dp_walk_simple(dev->full_configuration_descriptor,
+	    dev->full_configuration_descriptor_size,
+	    usb_dp_standard_descriptor_nesting,
+	    find_string_indexes_callback,
+	    &str_mask);
+
+	if (str_mask == 0) {
+		printf("Device does not support string descriptors.\n");
+		return;
+	}
+
 	/* Get supported languages. */
 	l18_win_locales_t *langs;
@@ -305,15 +320,4 @@
 	}
 	printf(".\n");
-
-	/* Find used indexes. Device with more than 64 strings are very rare.
-	 */
-	uint64_t str_mask = 0;
-	find_string_indexes_callback((uint8_t *)&dev->device_descriptor, 0,
-	    &str_mask);
-	usb_dp_walk_simple(dev->full_configuration_descriptor,
-	    dev->full_configuration_descriptor_size,
-	    usb_dp_standard_descriptor_nesting,
-	    find_string_indexes_callback,
-	    &str_mask);
 
 	/* Get all strings and dump them. */
Index: uspace/app/usbinfo/main.c
===================================================================
--- uspace/app/usbinfo/main.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/app/usbinfo/main.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -44,4 +44,5 @@
 #include <loc.h>
 #include <usb/hc.h>
+#include <usb/dev.h>
 #include <usb/dev/pipes.h>
 #include "usbinfo.h"
Index: uspace/app/usbinfo/usbinfo.h
===================================================================
--- uspace/app/usbinfo/usbinfo.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/app/usbinfo/usbinfo.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -44,6 +44,7 @@
 
 typedef struct {
+	usb_hc_connection_t hc_conn;
+	usb_device_connection_t wire;
 	usb_pipe_t ctrl_pipe;
-	usb_device_connection_t wire;
 	usb_standard_device_descriptor_t device_descriptor;
 	uint8_t *full_configuration_descriptor;
Index: uspace/app/websrv/websrv.c
===================================================================
--- uspace/app/websrv/websrv.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/app/websrv/websrv.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -49,4 +49,5 @@
 
 #define PORT_NUMBER 8080
+#define BACKLOG_SIZE 3
 
 #define WEB_ROOT "/data/web"
@@ -275,5 +276,5 @@
 	}
 
-	rc = listen(listen_sd, 1);
+	rc = listen(listen_sd, BACKLOG_SIZE);
 	if (rc != EOK) {
 		printf("Error calling listen() (%d).\n", rc);
@@ -304,4 +305,5 @@
 		if (rc != EOK) {
 			printf("Error closing connection socket: %d\n", rc);
+			closesocket(listen_sd);
 			return 1;
 		}
Index: uspace/dist/data/web/index.htm
===================================================================
--- uspace/dist/data/web/index.htm	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/dist/data/web/index.htm	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -7,4 +7,5 @@
     <body>
         <h1>Hello from HelenOS!</h1>
+        <img src="helenos.png" alt="" style="float: left; margin: 6px;">
         <p>
             This web page is brought to you by courtesy of HelenOS web server
Index: uspace/drv/bus/isa/Makefile
===================================================================
--- uspace/drv/bus/isa/Makefile	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/isa/Makefile	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -1,4 +1,5 @@
 #
 # Copyright (c) 2010 Lenka Trochtova
+# Copyright (c) 2011 Jan Vesely
 # All rights reserved.
 #
@@ -33,4 +34,5 @@
 
 SOURCES = \
+	i8237.c \
 	isa.c
 
Index: uspace/drv/bus/isa/i8237.c
===================================================================
--- uspace/drv/bus/isa/i8237.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
+++ uspace/drv/bus/isa/i8237.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -0,0 +1,430 @@
+/*
+ * 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 isa
+ * @{
+ */
+
+/** @file
+ * @brief DMA controller management
+ */
+
+#include <assert.h>
+#include <bool.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <ddf/log.h>
+#include "i8237.h"
+
+/** DMA Slave controller I/O Address. */
+#define DMA_CONTROLLER_FIRST_BASE  ((void *) 0x00)
+
+/** DMA Master controller I/O Address. */
+#define DMA_CONTROLLER_SECOND_BASE  ((void *) 0xc0)
+
+/** Shared DMA page address register I/O address. */
+#define DMA_CONTROLLER_PAGE_BASE  ((void *) 0x81)
+
+#define DMA_STATUS_REQ(x)       (1 << (((x) % 4) + 4))
+#define DMA_STATUS_COMPLETE(x)  (1 << ((x) % 4))
+
+/** http://wiki.osdev.org/DMA: The only bit that works is COND (bit 2) */
+#define DMA_COMMAND_COND  (1 << 2)  /**< Disables DMA controller */
+
+#define DMA_SINGLE_MASK_CHAN_SEL_MASK   0x03
+#define DMA_SINGLE_MASK_CHAN_SEL_SHIFT  0
+
+#define DMA_SINGLE_MASK_CHAN_TO_REG(x) \
+	(((x) & DMA_SINGLE_MASK_CHAN_SEL_MASK) << DMA_SINGLE_MASK_CHAN_SEL_SHIFT)
+
+#define DMA_SINGLE_MASK_MASKED_FLAG  (1 << 2)
+
+#define DMA_MODE_CHAN_SELECT_MASK   0x03
+#define DMA_MODE_CHAN_SELECT_SHIFT  0
+
+#define DMA_MODE_CHAN_TO_REG(x) \
+	(((x) & DMA_MODE_CHAN_SELECT_MASK) << DMA_MODE_CHAN_SELECT_SHIFT)
+
+#define DMA_MODE_CHAN_TRA_MASK       0x03
+#define DMA_MODE_CHAN_TRA_SHIFT      2
+#define DMA_MODE_CHAN_TRA_SELF_TEST  0
+#define DMA_MODE_CHAN_TRA_WRITE      0x01
+#define DMA_MODE_CHAN_TRA_READ       0x02
+
+#define DMA_MODE_CHAN_AUTO_FLAG  (1 << 4)
+#define DMA_MODE_CHAN_DOWN_FLAG  (1 << 5)
+
+#define DMA_MODE_CHAN_MODE_MASK     0x03
+#define DMA_MODE_CHAN_MODE_SHIFT    6
+#define DMA_MODE_CHAN_MODE_DEMAND   0
+#define DMA_MODE_CHAN_MODE_SINGLE   1
+#define DMA_MODE_CHAN_MODE_BLOCK    2
+#define DMA_MODE_CHAN_MODE_CASCADE  3
+
+#define DMA_MULTI_MASK_CHAN(x)  (1 << ((x) % 4))
+
+typedef struct {
+	uint8_t channel_start0;
+	uint8_t channel_count0;
+	uint8_t channel_start1;
+	uint8_t channel_count1;
+	uint8_t channel_start2;
+	uint8_t channel_count2;
+	uint8_t channel_start3;
+	uint8_t channel_count3;
+	
+	uint8_t command_status;
+	
+	/** Memory to memory transfers, NOT implemented on PCs */
+	uint8_t request;
+	uint8_t single_mask;
+	uint8_t mode;
+	uint8_t flip_flop;
+	
+	/*
+	 * Master reset sets Flip-Flop low, clears status,
+	 * sets all mask bits on.
+	 *
+	 * Intermediate is not implemented on PCs.
+	 *
+	 */
+	uint8_t master_reset;
+	uint8_t mask_reset;
+	uint8_t multi_mask;
+} dma_controller_regs_first_t;
+
+typedef struct {
+	uint8_t channel_start4;
+	uint8_t reserved0;
+	uint8_t channel_count4;
+	uint8_t reserved1;
+	uint8_t channel_start5;
+	uint8_t reserved2;
+	uint8_t channel_count5;
+	uint8_t reserved3;
+	uint8_t channel_start6;
+	uint8_t reserved4;
+	uint8_t channel_count6;
+	uint8_t reserved5;
+	uint8_t channel_start7;
+	uint8_t reserved6;
+	uint8_t channel_count7;
+	
+	uint8_t command_status;
+	uint8_t reserved8;
+	uint8_t request;
+	uint8_t reserved9;
+	uint8_t single_mask;
+	uint8_t reserveda;
+	uint8_t mode;
+	uint8_t reservedb;
+	uint8_t flip_flop;
+	uint8_t reservedc;
+	uint8_t master_reset;
+	uint8_t reservedd;
+	uint8_t multi_mask;
+} dma_controller_regs_second_t;
+
+typedef struct {
+	uint8_t channel2;
+	uint8_t channel3;
+	uint8_t channel1;
+	uint8_t reserved0;
+	uint8_t reserved1;
+	uint8_t reserved2;
+	uint8_t channel0;
+	uint8_t reserved3;
+	uint8_t channel6;
+	uint8_t channel7;
+	uint8_t channel5;
+	uint8_t reserved4;
+	uint8_t reserved5;
+	uint8_t reserved6;
+	uint8_t channel4;
+} dma_page_regs_t;
+
+/** Addresses needed to setup a DMA channel. */
+typedef struct {
+	ioport8_t *offset_reg_address;
+	ioport8_t *size_reg_address;
+	ioport8_t *page_reg_address;
+	ioport8_t *single_mask_address;
+	ioport8_t *mode_address;
+	ioport8_t *flip_flop_address;
+} dma_channel_t;
+
+typedef struct {
+	dma_channel_t channels[8];
+	dma_page_regs_t *page_table;
+	dma_controller_regs_first_t *first;
+	dma_controller_regs_second_t *second;
+	bool initialized;
+} dma_controller_t;
+
+static fibril_mutex_t guard = FIBRIL_MUTEX_INITIALIZER(guard);
+
+/** Standard i8237 DMA controller.
+ *
+ * http://zet.aluzina.org/index.php/8237_DMA_controller#DMA_Channel_Registers
+ *
+ */
+static dma_controller_t controller_8237 = {
+	.channels = {
+		/* The first chip 8-bit */
+		{
+			(uint8_t *) 0x00,
+			(uint8_t *) 0x01,
+			(uint8_t *) 0x87,
+			(uint8_t *) 0x0a,
+			(uint8_t *) 0x0b,
+			(uint8_t *) 0x0c,
+		},
+		{
+			(uint8_t *) 0x02,
+			(uint8_t *) 0x03,
+			(uint8_t *) 0x83,
+			(uint8_t *) 0x0a,
+			(uint8_t *) 0x0b,
+			(uint8_t *) 0x0c,
+		},
+		{
+			(uint8_t *) 0x04,
+			(uint8_t *) 0x05,
+			(uint8_t *) 0x81,
+			(uint8_t *) 0x0a,
+			(uint8_t *) 0x0b,
+			(uint8_t *) 0x0c,
+		},
+		{
+			(uint8_t *) 0x06,
+			(uint8_t *) 0x07,
+			(uint8_t *) 0x82,
+			(uint8_t *) 0x0a,
+			(uint8_t *) 0x0b,
+			(uint8_t *) 0x0c,
+		},
+		
+		/* The second chip 16-bit */
+		{
+			(uint8_t *) 0xc0,
+			(uint8_t *) 0xc2,
+			(uint8_t *) 0x8f,
+			(uint8_t *) 0xd4,
+			(uint8_t *) 0xd6,
+			(uint8_t *) 0xd8,
+		},
+		{
+			(uint8_t *) 0xc4,
+			(uint8_t *) 0xc6,
+			(uint8_t *) 0x8b,
+			(uint8_t *) 0xd4,
+			(uint8_t *) 0xd6,
+			(uint8_t *) 0xd8,
+		},
+		{
+			(uint8_t *) 0xc8,
+			(uint8_t *) 0xca,
+			(uint8_t *) 0x89,
+			(uint8_t *) 0xd4,
+			(uint8_t *) 0xd6,
+			(uint8_t *) 0xd8,
+		},
+		{
+			(uint8_t *) 0xcc,
+			(uint8_t *) 0xce,
+			(uint8_t *) 0x8a,
+			(uint8_t *) 0xd4,
+			(uint8_t *) 0xd6,
+			(uint8_t *) 0xd8,
+		},
+	},
+	
+	.page_table = NULL,
+	.first = NULL,
+	.second = NULL,
+	.initialized = false,
+};
+
+/* Initialize I/O access to DMA controller I/O ports.
+ *
+ * @param controller DMA Controller structure to initialize.
+ *
+ * @return Error code.
+ *
+ */
+static inline int dma_controller_init(dma_controller_t *controller)
+{
+	assert(controller);
+	int ret = pio_enable(DMA_CONTROLLER_PAGE_BASE, sizeof(dma_page_regs_t),
+	    (void **) &controller->page_table);
+	if (ret != EOK)
+		return EIO;
+	
+	ret = pio_enable(DMA_CONTROLLER_FIRST_BASE,
+	    sizeof(dma_controller_regs_first_t), (void **) &controller->first);
+	if (ret != EOK)
+		return EIO;
+	
+	ret = pio_enable(DMA_CONTROLLER_SECOND_BASE,
+		sizeof(dma_controller_regs_second_t), (void **) &controller->second);
+	if (ret != EOK)
+		return EIO;
+	
+	controller->initialized = true;
+	
+	/* Reset the controller */
+	pio_write_8(&controller->second->master_reset, 0xff);
+	pio_write_8(&controller->first->master_reset, 0xff);
+	
+	return EOK;
+}
+
+/** Setup DMA channel to specified place and mode.
+ *
+ * @param channel DMA Channel 1, 2, 3 for 8 bit transfers,
+ *                    5, 6, 7 for 16 bit.
+ * @param pa      Physical address of the buffer. Must be < 16 MB
+ *                for 16 bit and < 1 MB for 8 bit transfers.
+ * @param size    DMA buffer size, limited to 64 KB.
+ * @param mode    Mode of the DMA channel:
+ *                - Read or Write
+ *                - Allow automatic reset
+ *                - Use address decrement instead of increment
+ *                - Use SINGLE/BLOCK/ON DEMAND transfer mode
+ *
+ * @return Error code.
+ *
+ */
+int dma_setup_channel(unsigned int channel, uint32_t pa, uint16_t size,
+    uint8_t mode)
+{
+	if ((channel == 0) || (channel == 4))
+		return ENOTSUP;
+	
+	if (channel > 7)
+		return ENOENT;
+	
+	/* DMA is limited to 24bit addresses. */
+	if (pa >= (1 << 24))
+		return EINVAL;
+	
+	/* 8 bit channels use only 4 bits from the page register. */
+	if ((channel > 0) && (channel < 4) && (pa >= (1 << 20)))
+		return EINVAL;
+	
+	fibril_mutex_lock(&guard);
+	
+	if (!controller_8237.initialized)
+		dma_controller_init(&controller_8237);
+	
+	if (!controller_8237.initialized) {
+		fibril_mutex_unlock(&guard);
+		return EIO;
+	}
+	
+	/* 16 bit transfers are a bit special */
+	ddf_msg(LVL_DEBUG, "Unspoiled address: %p and size: %zu.", pa, size);
+	if (channel > 4) {
+		/* Size must be aligned to 16 bits */
+		if ((size & 1) != 0) {
+			fibril_mutex_unlock(&guard);
+			return EINVAL;
+		}
+		
+		size >>= 1;
+		
+		/* Address is fun: lower 16 bits need to be shifted by 1 */
+		pa = ((pa & 0xffff) >> 1) | (pa & 0xff0000);
+	}
+	
+	const dma_channel_t dma_channel = controller_8237.channels[channel];
+	
+	ddf_msg(LVL_DEBUG, "Setting channel %u, to address %p(%zu), mode %hhx.",
+	    channel, pa, size, mode);
+	
+	/* Mask DMA request */
+	uint8_t value = DMA_SINGLE_MASK_CHAN_TO_REG(channel) |
+	    DMA_SINGLE_MASK_MASKED_FLAG;
+	pio_write_8(dma_channel.single_mask_address, value);
+	
+	/* Set mode */
+	value = DMA_MODE_CHAN_TO_REG(channel) | mode;
+	ddf_msg(LVL_DEBUG2, "Writing mode byte: %p:%hhx.",
+	    dma_channel.mode_address, value);
+	pio_write_8(dma_channel.mode_address, value);
+	
+	/* Set address - reset flip-flop */
+	pio_write_8(dma_channel.flip_flop_address, 0);
+	
+	/* Low byte */
+	value = pa & 0xff;
+	ddf_msg(LVL_DEBUG2, "Writing address low byte: %p:%hhx.",
+	    dma_channel.offset_reg_address, value);
+	pio_write_8(dma_channel.offset_reg_address, value);
+	
+	/* High byte */
+	value = (pa >> 8) & 0xff;
+	ddf_msg(LVL_DEBUG2, "Writing address high byte: %p:%hhx.",
+	    dma_channel.offset_reg_address, value);
+	pio_write_8(dma_channel.offset_reg_address, value);
+	
+	/* Page address - third byte */
+	value = (pa >> 16) & 0xff;
+	ddf_msg(LVL_DEBUG2, "Writing address page byte: %p:%hhx.",
+	    dma_channel.page_reg_address, value);
+	pio_write_8(dma_channel.page_reg_address, value);
+	
+	/* Set size - reset flip-flop */
+	pio_write_8(dma_channel.flip_flop_address, 0);
+	
+	/* Low byte */
+	value = (size - 1) & 0xff;
+	ddf_msg(LVL_DEBUG2, "Writing size low byte: %p:%hhx.",
+	    dma_channel.size_reg_address, value);
+	pio_write_8(dma_channel.size_reg_address, value);
+	
+	/* High byte */
+	value = ((size - 1) >> 8) & 0xff;
+	ddf_msg(LVL_DEBUG2, "Writing size high byte: %p:%hhx.",
+	    dma_channel.size_reg_address, value);
+	pio_write_8(dma_channel.size_reg_address, value);
+	
+	/* Unmask DMA request */
+	value = DMA_SINGLE_MASK_CHAN_TO_REG(channel);
+	pio_write_8(dma_channel.single_mask_address, value);
+	
+	fibril_mutex_unlock(&guard);
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/isa/i8237.h
===================================================================
--- uspace/drv/bus/isa/i8237.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
+++ uspace/drv/bus/isa/i8237.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -0,0 +1,46 @@
+/*
+ * 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 isa
+ * @{
+ */
+
+/** @file
+ * @brief DMA memory management
+ */
+
+#ifndef DRV_BUS_ISA_I8237_H
+#define DRV_BUS_ISA_I8237_H
+
+extern int dma_setup_channel(unsigned int, uint32_t, uint16_t, uint8_t);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/isa/isa.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -2,4 +2,5 @@
  * Copyright (c) 2010 Lenka Trochtova
  * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
  *
@@ -52,4 +53,8 @@
 #include <fcntl.h>
 #include <sys/stat.h>
+#include <ipc/irc.h>
+#include <ipc/services.h>
+#include <sysinfo.h>
+#include <ns.h>
 
 #include <ddf/driver.h>
@@ -61,4 +66,6 @@
 #include <device/hw_res.h>
 
+#include "i8237.h"
+
 #define NAME "isa"
 #define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
@@ -70,5 +77,5 @@
 #define ISA_FUN(fun) ((isa_fun_t *) ((fun)->driver_data))
 
-#define ISA_MAX_HW_RES 4
+#define ISA_MAX_HW_RES 5
 
 typedef struct {
@@ -96,12 +103,70 @@
 static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
 {
-	/* TODO */
-
-	return false;
+	/* This is an old ugly way, copied from pci driver */
+	assert(fnode);
+	isa_fun_t *isa_fun = fnode->driver_data;
+
+	sysarg_t apic;
+	sysarg_t i8259;
+	
+	async_sess_t *irc_sess = NULL;
+	
+	if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
+	    || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) {
+		irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+		    SERVICE_IRC, 0, 0);
+	}
+	
+	if (!irc_sess)
+		return false;
+	
+	assert(isa_fun);
+	const hw_resource_list_t *res = &isa_fun->hw_resources;
+	assert(res);
+	for (size_t i = 0; i < res->count; ++i) {
+		if (res->resources[i].type == INTERRUPT) {
+			const int irq = res->resources[i].res.interrupt.irq;
+			
+			async_exch_t *exch = async_exchange_begin(irc_sess);
+			const int rc =
+			    async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq);
+			async_exchange_end(exch);
+			
+			if (rc != EOK) {
+				async_hangup(irc_sess);
+				return false;
+			}
+		}
+	}
+	
+	async_hangup(irc_sess);
+	return true;
+}
+
+static int isa_dma_channel_fun_setup(ddf_fun_t *fnode,
+    unsigned int channel, uint32_t pa, uint16_t size, uint8_t mode)
+{
+	assert(fnode);
+	isa_fun_t *isa_fun = fnode->driver_data;
+	const hw_resource_list_t *res = &isa_fun->hw_resources;
+	assert(res);
+	
+	const unsigned int ch = channel;
+	for (size_t i = 0; i < res->count; ++i) {
+		if (((res->resources[i].type == DMA_CHANNEL_16) &&
+		    (res->resources[i].res.dma_channel.dma16 == ch)) ||
+		    ((res->resources[i].type == DMA_CHANNEL_8) &&
+		    (res->resources[i].res.dma_channel.dma8 == ch))) {
+			return dma_setup_channel(channel, pa, size, mode);
+		}
+	}
+	
+	return EINVAL;
 }
 
 static hw_res_ops_t isa_fun_hw_res_ops = {
-	&isa_get_fun_resources,
-	&isa_enable_fun_interrupt
+	.get_resource_list = isa_get_fun_resources,
+	.enable_interrupt = isa_enable_fun_interrupt,
+	.dma_channel_setup = isa_dma_channel_fun_setup,
 };
 
@@ -274,4 +339,37 @@
 }
 
+static void isa_fun_set_dma(isa_fun_t *fun, int dma)
+{
+	size_t count = fun->hw_resources.count;
+	hw_resource_t *resources = fun->hw_resources.resources;
+	
+	if (count < ISA_MAX_HW_RES) {
+		if ((dma > 0) && (dma < 4)) {
+			resources[count].type = DMA_CHANNEL_8;
+			resources[count].res.dma_channel.dma8 = dma;
+			
+			fun->hw_resources.count++;
+			ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
+			    fun->fnode->name);
+			
+			return;
+		}
+
+		if ((dma > 4) && (dma < 8)) {
+			resources[count].type = DMA_CHANNEL_16;
+			resources[count].res.dma_channel.dma16 = dma;
+			
+			fun->hw_resources.count++;
+			ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
+			    fun->fnode->name);
+			
+			return;
+		}
+		
+		ddf_msg(LVL_WARN, "Skipped dma 0x%x for function %s", dma,
+		    fun->fnode->name);
+	}
+}
+
 static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len)
 {
@@ -303,4 +401,16 @@
 	if (val != end)
 		isa_fun_set_irq(fun, irq);
+}
+
+static void fun_parse_dma(isa_fun_t *fun, char *val)
+{
+	unsigned int dma = 0;
+	char *end = NULL;
+	
+	val = skip_spaces(val);
+	dma = (unsigned int) strtol(val, &end, 10);
+	
+	if (val != end)
+		isa_fun_set_dma(fun, dma);
 }
 
@@ -396,4 +506,5 @@
 	if (!prop_parse(fun, line, "io_range", &fun_parse_io_range) &&
 	    !prop_parse(fun, line, "irq", &fun_parse_irq) &&
+	    !prop_parse(fun, line, "dma", &fun_parse_dma) &&
 	    !prop_parse(fun, line, "match", &fun_parse_match_id)) {
 
@@ -406,5 +517,5 @@
 {
 	fun->hw_resources.resources =
-	    (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
+	    (hw_resource_t *) malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
 }
 
@@ -590,5 +701,5 @@
 
 
-static void isa_init() 
+static void isa_init()
 {
 	ddf_log_init(NAME, LVL_ERROR);
Index: uspace/drv/bus/isa/isa.dev
===================================================================
--- uspace/drv/bus/isa/isa.dev	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/isa/isa.dev	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -18,2 +18,10 @@
 	irq 5
 	io_range 300 20
+
+sb16:
+	match 100 isa/sb16
+	io_range 220 20
+	io_range 330 2
+	irq 5
+	dma 1
+	dma 5
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -187,6 +187,6 @@
 
 static hw_res_ops_t pciintel_hw_res_ops = {
-	&pciintel_get_resources,
-	&pciintel_enable_interrupt
+	.get_resource_list = &pciintel_get_resources,
+	.enable_interrupt = &pciintel_enable_interrupt,
 };
 
Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -137,6 +137,4 @@
 		return ret;
 	}
-	usb_device_manager_bind_address(&instance->generic.dev_manager,
-	    instance->rh.address, hub_fun->handle);
 
 #define CHECK_RET_UNREG_RETURN(ret, message...) \
@@ -150,4 +148,5 @@
 	return ret; \
 } else (void)0
+
 	ret = usb_endpoint_manager_add_ep(
 	    &instance->generic.ep_manager, instance->rh.address, 0,
@@ -165,4 +164,10 @@
 	CHECK_RET_UNREG_RETURN(ret,
 	    "Failed to bind root hub function: %s.\n", str_error(ret));
+
+	ret = usb_device_manager_bind_address(&instance->generic.dev_manager,
+	    instance->rh.address, hub_fun->handle);
+	if (ret != EOK)
+		usb_log_warning("Failed to bind root hub address: %s.\n",
+		    str_error(ret));
 
 	return EOK;
Index: uspace/drv/bus/usb/ohci/ohci.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -140,23 +140,23 @@
 int device_setup_ohci(ddf_dev_t *device)
 {
-	assert(device);
-
-	ohci_t *instance = malloc(sizeof(ohci_t));
+	if (device == NULL)
+		return EBADMEM;
+
+	ohci_t *instance = ddf_dev_data_alloc(device,sizeof(ohci_t));
 	if (instance == NULL) {
 		usb_log_error("Failed to allocate OHCI driver.\n");
 		return ENOMEM;
 	}
-	instance->rh_fun = NULL;
-	instance->hc_fun = NULL;
 
 #define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
 if (ret != EOK) { \
 	if (instance->hc_fun) { \
+		instance->hc_fun->driver_data = NULL; \
 		ddf_fun_destroy(instance->hc_fun); \
 	} \
 	if (instance->rh_fun) { \
+		instance->rh_fun->driver_data = NULL; \
 		ddf_fun_destroy(instance->rh_fun); \
 	} \
-	free(instance); \
 	usb_log_error(message); \
 	return ret; \
@@ -219,6 +219,4 @@
 	    "Failed to init ohci_hcd: %s.\n", str_error(ret));
 
-	device->driver_data = instance;
-
 #define CHECK_RET_FINI_RETURN(ret, message...) \
 if (ret != EOK) { \
Index: uspace/drv/bus/usb/ohci/ohci_batch.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_batch.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/ohci/ohci_batch.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -34,4 +34,5 @@
 #include <errno.h>
 #include <str_error.h>
+#include <macros.h>
 
 #include <usb/usb.h>
@@ -53,6 +54,9 @@
 		return;
 	if (ohci_batch->tds) {
+		const ohci_endpoint_t *ohci_ep =
+		    ohci_endpoint_get(ohci_batch->usb_batch->ep);
+		assert(ohci_ep);
 		for (unsigned i = 0; i < ohci_batch->td_count; ++i) {
-			if (i != ohci_batch->leave_td)
+			if (ohci_batch->tds[i] != ohci_ep->td)
 				free32(ohci_batch->tds[i]);
 		}
@@ -64,4 +68,8 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Finishes usb_transfer_batch and destroys the structure.
+ *
+ * @param[in] uhci_batch Instance to finish and destroy.
+ */
 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *ohci_batch)
 {
@@ -69,9 +77,18 @@
 	assert(ohci_batch->usb_batch);
 	usb_transfer_batch_finish(ohci_batch->usb_batch,
-	    ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size,
-	    ohci_batch->usb_batch->buffer_size);
+	    ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size);
 	ohci_transfer_batch_dispose(ohci_batch);
 }
 /*----------------------------------------------------------------------------*/
+/** Allocate memory and initialize internal data structure.
+ *
+ * @param[in] usb_batch Pointer to generic USB batch structure.
+ * @return Valid pointer if all structures were successfully created,
+ * NULL otherwise.
+ *
+ * Determines the number of needed transfer descriptors (TDs).
+ * Prepares a transport buffer (that is accessible by the hardware).
+ * Initializes parameters needed for the transfer and callback.
+ */
 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *usb_batch)
 {
@@ -105,5 +122,4 @@
 	ohci_batch->ed = ohci_endpoint_get(usb_batch->ep)->ed;
 	ohci_batch->tds[0] = ohci_endpoint_get(usb_batch->ep)->td;
-	ohci_batch->leave_td = 0;
 
 	for (unsigned i = 1; i <= ohci_batch->td_count; ++i) {
@@ -152,5 +168,5 @@
  * completes with the last TD.
  */
-bool ohci_transfer_batch_is_complete(ohci_transfer_batch_t *ohci_batch)
+bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *ohci_batch)
 {
 	assert(ohci_batch);
@@ -174,5 +190,5 @@
 
 	/* Assume we will leave the last(unused) TD behind */
-	ohci_batch->leave_td = ohci_batch->td_count;
+	unsigned leave_td = ohci_batch->td_count;
 
 	/* Check all TDs */
@@ -212,14 +228,14 @@
 			 * It will be the one TD we leave behind.
 			 */
-			ohci_batch->leave_td = i + 1;
+			leave_td = i + 1;
 
 			/* Check TD assumption */
-			const uint32_t pa = addr_to_phys(
-			    ohci_batch->tds[ohci_batch->leave_td]);
-			assert((ohci_batch->ed->td_head & ED_TDTAIL_PTR_MASK)
+			const uint32_t pa =
+			    addr_to_phys(ohci_batch->tds[leave_td]);
+			assert((ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK)
 			    == pa);
 
 			ed_set_tail_td(ohci_batch->ed,
-			    ohci_batch->tds[ohci_batch->leave_td]);
+			    ohci_batch->tds[leave_td]);
 
 			/* Clear possible ED HALT */
@@ -234,5 +250,5 @@
 	ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep);
 	assert(ohci_ep);
-	ohci_ep->td = ohci_batch->tds[ohci_batch->leave_td];
+	ohci_ep->td = ohci_batch->tds[leave_td];
 
 	/* Make sure that we are leaving the right TD behind */
@@ -248,5 +264,5 @@
  * @param[in] ohci_batch Batch structure to use
  */
-void ohci_transfer_batch_commit(ohci_transfer_batch_t *ohci_batch)
+void ohci_transfer_batch_commit(const ohci_transfer_batch_t *ohci_batch)
 {
 	assert(ohci_batch);
@@ -295,6 +311,5 @@
 	while (remain_size > 0) {
 		const size_t transfer_size =
-		    remain_size > OHCI_TD_MAX_TRANSFER ?
-		    OHCI_TD_MAX_TRANSFER : remain_size;
+		    min(remain_size, OHCI_TD_MAX_TRANSFER);
 		toggle = 1 - toggle;
 
@@ -378,4 +393,5 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Transfer setup table. */
 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t) =
 {
Index: uspace/drv/bus/usb/ohci/ohci_batch.h
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_batch.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/ohci/ohci_batch.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -53,6 +53,4 @@
 	/** Number of TDs used by the transfer */
 	size_t td_count;
-	/** Dummy TD to be left at the ED and used by the next transfer */
-	size_t leave_td;
 	/** Data buffer, must be accessible by the OHCI hw. */
 	char *device_buffer;
@@ -62,6 +60,6 @@
 
 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *batch);
-bool ohci_transfer_batch_is_complete(ohci_transfer_batch_t *batch);
-void ohci_transfer_batch_commit(ohci_transfer_batch_t *batch);
+bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *batch);
+void ohci_transfer_batch_commit(const ohci_transfer_batch_t *batch);
 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch);
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/bus/usb/ohci/pci.c
===================================================================
--- uspace/drv/bus/usb/ohci/pci.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/ohci/pci.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -42,5 +42,5 @@
 #include <ddi.h>
 #include <libarch/ddi.h>
-#include <device/hw_res.h>
+#include <device/hw_res_parsed.h>
 
 #include <usb/debug.h>
@@ -61,7 +61,4 @@
 {
 	assert(dev);
-	assert(mem_reg_address);
-	assert(mem_reg_size);
-	assert(irq_no);
 
 	async_sess_t *parent_sess =
@@ -71,48 +68,27 @@
 		return ENOMEM;
 
-	hw_resource_list_t hw_resources;
-	int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
+	hw_res_list_parsed_t hw_res;
+	hw_res_list_parsed_init(&hw_res);
+	const int ret =  hw_res_get_list_parsed(parent_sess, &hw_res, 0);
 	async_hangup(parent_sess);
-	if (rc != EOK) {
-		return rc;
+	if (ret != EOK) {
+		return ret;
 	}
 
-	uintptr_t mem_address = 0;
-	size_t mem_size = 0;
-	bool mem_found = false;
+	/* We want one irq and one mem range. */
+	if (hw_res.irqs.count != 1 || hw_res.mem_ranges.count != 1) {
+		hw_res_list_parsed_clean(&hw_res);
+		return EINVAL;
+	}
 
-	int irq = 0;
-	bool irq_found = false;
+	if (mem_reg_address)
+		*mem_reg_address = hw_res.mem_ranges.ranges[0].address;
+	if (mem_reg_size)
+		*mem_reg_size = hw_res.mem_ranges.ranges[0].size;
+	if (irq_no)
+		*irq_no = hw_res.irqs.irqs[0];
 
-	for (size_t 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;
-			usb_log_debug2("Found interrupt: %d.\n", irq);
-			break;
-		case MEM_RANGE:
-			if (res->res.mem_range.address != 0
-			    && res->res.mem_range.size != 0 ) {
-				mem_address = res->res.mem_range.address;
-				mem_size = res->res.mem_range.size;
-				usb_log_debug2("Found mem: %p %zu.\n",
-				    (void *) mem_address, mem_size);
-				mem_found = true;
-			}
-		default:
-			break;
-		}
-	}
-	free(hw_resources.resources);
-
-	if (mem_found && irq_found) {
-		*mem_reg_address = mem_address;
-		*mem_reg_size = mem_size;
-		*irq_no = irq;
-		return EOK;
-	}
-	return ENOENT;
+	hw_res_list_parsed_clean(&hw_res);
+	return EOK;
 }
 
Index: uspace/drv/bus/usb/ohci/root_hub.c
===================================================================
--- uspace/drv/bus/usb/ohci/root_hub.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/ohci/root_hub.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -100,5 +100,5 @@
 	.attributes = USB_TRANSFER_INTERRUPT,
 	.descriptor_type = USB_DESCTYPE_ENDPOINT,
-	.endpoint_address = 1 + (1 << 7),
+	.endpoint_address = 1 | (1 << 7),
 	.length = sizeof(usb_standard_endpoint_descriptor_t),
 	.max_packet_size = 2,
@@ -109,26 +109,33 @@
 static void rh_init_descriptors(rh_t *instance);
 static uint16_t create_interrupt_mask(const rh_t *instance);
-static int get_status(const rh_t *instance, usb_transfer_batch_t *request);
-static int get_descriptor(const rh_t *instance, usb_transfer_batch_t *request);
-static int set_feature(const rh_t *instance, usb_transfer_batch_t *request);
-static int clear_feature(const rh_t *instance, usb_transfer_batch_t *request);
+static void get_status(const rh_t *instance, usb_transfer_batch_t *request);
+static void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request);
+static void set_feature(const rh_t *instance, usb_transfer_batch_t *request);
+static void clear_feature(const rh_t *instance, usb_transfer_batch_t *request);
 static int set_feature_port(
     const rh_t *instance, uint16_t feature, uint16_t port);
 static int clear_feature_port(
     const rh_t *instance, uint16_t feature, uint16_t port);
-static int control_request(rh_t *instance, usb_transfer_batch_t *request);
+static void control_request(rh_t *instance, usb_transfer_batch_t *request);
 static inline void interrupt_request(
     usb_transfer_batch_t *request, uint16_t mask, size_t size)
 {
 	assert(request);
-
-	request->transfered_size = size;
 	usb_transfer_batch_finish_error(request, &mask, size, EOK);
-}
-
-#define TRANSFER_OK(bytes) \
+	usb_transfer_batch_destroy(request);
+}
+
+#define TRANSFER_END_DATA(request, data, bytes) \
 do { \
-	request->transfered_size = bytes; \
-	return EOK; \
+	usb_transfer_batch_finish_error(request, data, bytes, EOK); \
+	usb_transfer_batch_destroy(request); \
+	return; \
+} while (0)
+
+#define TRANSFER_END(request, error) \
+do { \
+	usb_transfer_batch_finish_error(request, NULL, 0, error); \
+	usb_transfer_batch_destroy(request); \
+	return; \
 } while (0)
 
@@ -212,20 +219,20 @@
 	case USB_TRANSFER_CONTROL:
 		usb_log_debug("Root hub got CONTROL packet\n");
-		const int ret = control_request(instance, request);
-		usb_transfer_batch_finish_error(request, NULL, 0, ret);
+		control_request(instance, request);
 		break;
+
 	case USB_TRANSFER_INTERRUPT:
 		usb_log_debug("Root hub got INTERRUPT packet\n");
 		fibril_mutex_lock(&instance->guard);
 		assert(instance->unfinished_interrupt_transfer == NULL);
-		const uint16_t mask = create_interrupt_mask(instance);
+		uint16_t mask = create_interrupt_mask(instance);
 		if (mask == 0) {
-			usb_log_debug("No changes..\n");
+			usb_log_debug("No changes...\n");
 			instance->unfinished_interrupt_transfer = request;
-			fibril_mutex_unlock(&instance->guard);
-			return;
+		} else {
+			usb_log_debug("Processing changes...\n");
+			interrupt_request(
+			    request, mask, instance->interrupt_mask_size);
 		}
-		usb_log_debug("Processing changes...\n");
-		interrupt_request(request, mask, instance->interrupt_mask_size);
 		fibril_mutex_unlock(&instance->guard);
 		break;
@@ -233,7 +240,6 @@
 	default:
 		usb_log_error("Root hub got unsupported request.\n");
-		usb_transfer_batch_finish_error(request, NULL, 0, EINVAL);
-	}
-	usb_transfer_batch_destroy(request);
+		TRANSFER_END(request, ENOTSUP);
+	}
 }
 /*----------------------------------------------------------------------------*/
@@ -251,9 +257,7 @@
 	if (instance->unfinished_interrupt_transfer) {
 		usb_log_debug("Finalizing interrupt transfer\n");
-		const uint16_t mask = create_interrupt_mask(instance);
+		uint16_t mask = create_interrupt_mask(instance);
 		interrupt_request(instance->unfinished_interrupt_transfer,
 		    mask, instance->interrupt_mask_size);
-		usb_transfer_batch_destroy(
-		    instance->unfinished_interrupt_transfer);
 		instance->unfinished_interrupt_transfer = NULL;
 	}
@@ -274,10 +278,10 @@
 
 	/* 7 bytes + 2 port bit fields (port count + global bit) */
-	const size_t size = 7 + (instance->interrupt_mask_size * 2);
+	size_t size = 7 + (instance->interrupt_mask_size * 2);
 	assert(size <= HUB_DESCRIPTOR_MAX_SIZE);
 	instance->hub_descriptor_size = size;
 
-	const uint32_t hub_desc = instance->registers->rh_desc_a;
-	const uint32_t port_desc = instance->registers->rh_desc_b;
+	uint32_t hub_desc = instance->registers->rh_desc_a;
+	uint32_t port_desc = instance->registers->rh_desc_b;
 
 	/* bDescLength */
@@ -384,39 +388,80 @@
  * @return error code
  */
-int get_status(const rh_t *instance, usb_transfer_batch_t *request)
+void get_status(const rh_t *instance, usb_transfer_batch_t *request)
 {
 	assert(instance);
 	assert(request);
 
-	const usb_device_request_setup_packet_t *request_packet =
+
+	usb_device_request_setup_packet_t *request_packet =
 	    (usb_device_request_setup_packet_t*)request->setup_buffer;
 
-	if (request->buffer_size < 4) {
-		usb_log_error("Buffer too small for get status request.\n");
-		return EOVERFLOW;
-	}
-
+	switch (request_packet->request_type)
+	{
+	case USB_HUB_REQ_TYPE_GET_HUB_STATUS:
 	/* Hub status: just filter relevant info from rh_status reg */
-	if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) {
-		const uint32_t data = instance->registers->rh_status &
-		    (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG);
-		memcpy(request->buffer, &data, sizeof(data));
-		TRANSFER_OK(sizeof(data));
-	}
+		if (request->buffer_size < 4) {
+			usb_log_error("Buffer(%zu) too small for hub get "
+			    "status request.\n", request->buffer_size);
+			TRANSFER_END(request, EOVERFLOW);
+		} else {
+			uint32_t data = instance->registers->rh_status &
+			    (RHS_LPS_FLAG | RHS_LPSC_FLAG
+			        | RHS_OCI_FLAG | RHS_OCIC_FLAG);
+			TRANSFER_END_DATA(request, &data, sizeof(data));
+		}
 
 	/* Copy appropriate rh_port_status register, OHCI designers were
 	 * kind enough to make those bit values match USB specification */
-	if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) {
-		const unsigned port = request_packet->index;
-		if (port < 1 || port > instance->port_count)
-			return EINVAL;
-
-		const uint32_t data =
-		    instance->registers->rh_port_status[port - 1];
-		memcpy(request->buffer, &data, sizeof(data));
-		TRANSFER_OK(sizeof(data));
-	}
-
-	return ENOTSUP;
+	case USB_HUB_REQ_TYPE_GET_PORT_STATUS:
+		if (request->buffer_size < 4) {
+			usb_log_error("Buffer(%zu) too small for hub get "
+			    "status request.\n", request->buffer_size);
+			TRANSFER_END(request, EOVERFLOW);
+		} else {
+			unsigned port = request_packet->index;
+			if (port < 1 || port > instance->port_count)
+				TRANSFER_END(request, EINVAL);
+
+			uint32_t data =
+			    instance->registers->rh_port_status[port - 1];
+			TRANSFER_END_DATA(request, &data, sizeof(data));
+		}
+	case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE):
+		if (request->buffer_size < 2) {
+			usb_log_error("Buffer(%zu) too small for hub generic "
+			    "get status request.\n", request->buffer_size);
+			TRANSFER_END(request, EOVERFLOW);
+		} else {
+			uint16_t data =
+			    uint16_host2usb(USB_DEVICE_STATUS_SELF_POWERED);
+			TRANSFER_END_DATA(request, &data, sizeof(data));
+		}
+
+	case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE):
+		/* Hubs are allowed to have only one interface */
+		if (request_packet->index != 0)
+			TRANSFER_END(request, EINVAL);
+		/* Fall through, as the answer will be the same: 0x0000 */
+	case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT):
+		/* Endpoint 0 (default control) and 1 (interrupt) */
+		if (request_packet->index >= 2)
+			TRANSFER_END(request, EINVAL);
+
+		if (request->buffer_size < 2) {
+			usb_log_error("Buffer(%zu) too small for hub generic "
+			    "get status request.\n", request->buffer_size);
+			TRANSFER_END(request, EOVERFLOW);
+		} else {
+			/* Endpoints are OK. (We don't halt) */
+			uint16_t data = 0;
+			TRANSFER_END_DATA(request, &data, sizeof(data));
+		}
+
+	default:
+		usb_log_error("Unsupported GET_STATUS request.\n");
+		TRANSFER_END(request, ENOTSUP);
+	}
+
 }
 /*----------------------------------------------------------------------------*/
@@ -430,54 +475,52 @@
  * @return Error code
  */
-int get_descriptor(const rh_t *instance, usb_transfer_batch_t *request)
+void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request)
 {
 	assert(instance);
 	assert(request);
 
-	const usb_device_request_setup_packet_t *setup_request =
+	usb_device_request_setup_packet_t *setup_request =
 	    (usb_device_request_setup_packet_t *) request->setup_buffer;
-	size_t size;
-	const void *descriptor = NULL;
-	const uint16_t setup_request_value = setup_request->value_high;
-	//(setup_request->value_low << 8);
+	uint16_t setup_request_value = setup_request->value_high;
 	switch (setup_request_value)
 	{
 	case USB_DESCTYPE_HUB:
 		usb_log_debug2("USB_DESCTYPE_HUB\n");
-		/* Hub descriptor was generated locally */
-		descriptor = instance->descriptors.hub;
-		size = instance->hub_descriptor_size;
-		break;
+		/* Hub descriptor was generated locally.
+		 * Class specific request. */
+		TRANSFER_END_DATA(request, instance->descriptors.hub,
+		    instance->hub_descriptor_size);
 
 	case USB_DESCTYPE_DEVICE:
 		usb_log_debug2("USB_DESCTYPE_DEVICE\n");
-		/* Device descriptor is shared (No one should ask for it)*/
-		descriptor = &ohci_rh_device_descriptor;
-		size = sizeof(ohci_rh_device_descriptor);
-		break;
+		/* Device descriptor is shared
+		 * (No one should ask for it, as the device is already setup)
+		 * Standard USB device request. */
+		TRANSFER_END_DATA(request, &ohci_rh_device_descriptor,
+		    sizeof(ohci_rh_device_descriptor));
 
 	case USB_DESCTYPE_CONFIGURATION:
 		usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n");
 		/* Start with configuration and add others depending on
-		 * request size */
-		descriptor = &instance->descriptors;
-		size = instance->descriptors.configuration.total_length;
-		break;
+		 * request size. Standard USB request. */
+		TRANSFER_END_DATA(request, &instance->descriptors,
+		    instance->descriptors.configuration.total_length);
 
 	case USB_DESCTYPE_INTERFACE:
 		usb_log_debug2("USB_DESCTYPE_INTERFACE\n");
 		/* Use local interface descriptor. There is one and it
-		 * might be modified */
-		descriptor = &instance->descriptors.interface;
-		size = sizeof(instance->descriptors.interface);
-		break;
+		 * might be modified. Hub driver should not ask or this
+		 * descriptor as it is not part of standard requests set. */
+		TRANSFER_END_DATA(request, &instance->descriptors.interface,
+		    sizeof(instance->descriptors.interface));
 
 	case USB_DESCTYPE_ENDPOINT:
 		/* Use local endpoint descriptor. There is one
-		 * it might have max_packet_size field modified*/
+		 * it might have max_packet_size field modified. Hub driver
+		 * should not ask for this descriptor as it is not part
+		 * of standard requests set. */
 		usb_log_debug2("USB_DESCTYPE_ENDPOINT\n");
-		descriptor = &instance->descriptors.endpoint;
-		size = sizeof(instance->descriptors.endpoint);
-		break;
+		TRANSFER_END_DATA(request, &instance->descriptors.endpoint,
+		    sizeof(instance->descriptors.endpoint));
 
 	default:
@@ -489,12 +532,8 @@
 		    setup_request_value, setup_request->index,
 		    setup_request->length);
-		return EINVAL;
-	}
-	if (request->buffer_size < size) {
-		size = request->buffer_size;
-	}
-
-	memcpy(request->buffer, descriptor, size);
-	TRANSFER_OK(size);
+		TRANSFER_END(request, EINVAL);
+	}
+
+	TRANSFER_END(request, ENOTSUP);
 }
 /*----------------------------------------------------------------------------*/
@@ -604,10 +643,10 @@
  * @return error code
  */
-int set_feature(const rh_t *instance, usb_transfer_batch_t *request)
+void set_feature(const rh_t *instance, usb_transfer_batch_t *request)
 {
 	assert(instance);
 	assert(request);
 
-	const usb_device_request_setup_packet_t *setup_request =
+	usb_device_request_setup_packet_t *setup_request =
 	    (usb_device_request_setup_packet_t *) request->setup_buffer;
 	switch (setup_request->request_type)
@@ -615,6 +654,7 @@
 	case USB_HUB_REQ_TYPE_SET_PORT_FEATURE:
 		usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
-		return set_feature_port(instance,
+		int ret = set_feature_port(instance,
 		    setup_request->value, setup_request->index);
+		TRANSFER_END(request, ret);
 
 	case USB_HUB_REQ_TYPE_SET_HUB_FEATURE:
@@ -623,9 +663,10 @@
 		 * features. It makes no sense to SET either. */
 		usb_log_error("Invalid HUB set feature request.\n");
-		return ENOTSUP;
+		TRANSFER_END(request, ENOTSUP);
+	//TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL
 	default:
 		usb_log_error("Invalid set feature request type: %d\n",
 		    setup_request->request_type);
-		return EINVAL;
+		TRANSFER_END(request, ENOTSUP);
 	}
 }
@@ -640,13 +681,11 @@
  * @return error code
  */
-int clear_feature(const rh_t *instance, usb_transfer_batch_t *request)
+void clear_feature(const rh_t *instance, usb_transfer_batch_t *request)
 {
 	assert(instance);
 	assert(request);
 
-	const usb_device_request_setup_packet_t *setup_request =
+	usb_device_request_setup_packet_t *setup_request =
 	    (usb_device_request_setup_packet_t *) request->setup_buffer;
-
-	request->transfered_size = 0;
 
 	switch (setup_request->request_type)
@@ -654,6 +693,7 @@
 	case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE:
 		usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n");
-		return clear_feature_port(instance,
+		int ret = clear_feature_port(instance,
 		    setup_request->value, setup_request->index);
+		TRANSFER_END(request, ret);
 
 	case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE:
@@ -668,10 +708,11 @@
 		if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
 			instance->registers->rh_status = RHS_OCIC_FLAG;
-			TRANSFER_OK(0);
+			TRANSFER_END(request, EOK);
 		}
+	//TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL
 	default:
 		usb_log_error("Invalid clear feature request type: %d\n",
 		    setup_request->request_type);
-		return EINVAL;
+		TRANSFER_END(request, ENOTSUP);
 	}
 }
@@ -695,5 +736,5 @@
  * @return error code
  */
-int control_request(rh_t *instance, usb_transfer_batch_t *request)
+void control_request(rh_t *instance, usb_transfer_batch_t *request)
 {
 	assert(instance);
@@ -702,15 +743,15 @@
 	if (!request->setup_buffer) {
 		usb_log_error("Root hub received empty transaction!");
-		return EINVAL;
+		TRANSFER_END(request, EBADMEM);
 	}
 
 	if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) {
 		usb_log_error("Setup packet too small\n");
-		return EOVERFLOW;
+		TRANSFER_END(request, EOVERFLOW);
 	}
 
 	usb_log_debug2("CTRL packet: %s.\n",
 	    usb_debug_str_buffer((uint8_t *) request->setup_buffer, 8, 8));
-	const usb_device_request_setup_packet_t *setup_request =
+	usb_device_request_setup_packet_t *setup_request =
 	    (usb_device_request_setup_packet_t *) request->setup_buffer;
 	switch (setup_request->request)
@@ -718,45 +759,58 @@
 	case USB_DEVREQ_GET_STATUS:
 		usb_log_debug("USB_DEVREQ_GET_STATUS\n");
-		return get_status(instance, request);
+		get_status(instance, request);
+		break;
 
 	case USB_DEVREQ_GET_DESCRIPTOR:
 		usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
-		return get_descriptor(instance, request);
+		get_descriptor(instance, request);
+		break;
 
 	case USB_DEVREQ_GET_CONFIGURATION:
 		usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
-		if (request->buffer_size != 1)
-			return EINVAL;
-		request->buffer[0] = 1;
-		TRANSFER_OK(1);
+		if (request->buffer_size == 0)
+			TRANSFER_END(request, EOVERFLOW);
+		uint8_t config = 1;
+		TRANSFER_END_DATA(request, &config, sizeof(config));
 
 	case USB_DEVREQ_CLEAR_FEATURE:
-		usb_log_debug2("Processing request without "
-		    "additional data\n");
-		return clear_feature(instance, request);
+		usb_log_debug2("USB_DEVREQ_CLEAR_FEATURE\n");
+		clear_feature(instance, request);
+		break;
 
 	case USB_DEVREQ_SET_FEATURE:
-		usb_log_debug2("Processing request without "
-		    "additional data\n");
-		return set_feature(instance, request);
+		usb_log_debug2("USB_DEVREQ_SET_FEATURE\n");
+		set_feature(instance, request);
+		break;
 
 	case USB_DEVREQ_SET_ADDRESS:
-		usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
+		usb_log_debug("USB_DEVREQ_SET_ADDRESS: %u\n",
+		    setup_request->value);
+		if (uint16_usb2host(setup_request->value) > 127)
+			TRANSFER_END(request, EINVAL);
+
 		instance->address = setup_request->value;
-		TRANSFER_OK(0);
+		TRANSFER_END(request, EOK);
 
 	case USB_DEVREQ_SET_CONFIGURATION:
-		usb_log_debug("USB_DEVREQ_SET_CONFIGURATION\n");
-		/* We don't need to do anything */
-		TRANSFER_OK(0);
-
-	case USB_DEVREQ_SET_DESCRIPTOR: /* Not supported by OHCI RH */
+		usb_log_debug("USB_DEVREQ_SET_CONFIGURATION: %u\n",
+		    setup_request->value);
+		/* We have only one configuration, it's number is 1 */
+		if (uint16_usb2host(setup_request->value) != 1)
+			TRANSFER_END(request, EINVAL);
+		TRANSFER_END(request, EOK);
+
+	/* Both class specific and std is optional for hubs */
+	case USB_DEVREQ_SET_DESCRIPTOR:
+	/* Hubs have only one interface GET/SET is not supported */
+	case USB_DEVREQ_GET_INTERFACE:
+	case USB_DEVREQ_SET_INTERFACE:
 	default:
+		/* Hub class GET_STATE(2) falls in here too. */
 		usb_log_error("Received unsupported request: %d.\n",
 		    setup_request->request);
-		return ENOTSUP;
-	}
-}
-
+		TRANSFER_END(request, ENOTSUP);
+	}
+}
 /**
  * @}
Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -130,5 +130,5 @@
 			uhci_transfer_batch_t *batch =
 			    uhci_transfer_batch_from_link(item);
-			uhci_transfer_batch_call_dispose(batch);
+			uhci_transfer_batch_finish_dispose(batch);
 		}
 	}
Index: uspace/drv/bus/usb/uhci/pci.c
===================================================================
--- uspace/drv/bus/usb/uhci/pci.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/uhci/pci.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -26,5 +26,4 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /**
  * @addtogroup drvusbuhcihc
@@ -39,5 +38,5 @@
 #include <assert.h>
 #include <devman.h>
-#include <device/hw_res.h>
+#include <device/hw_res_parsed.h>
 
 #include <usb/debug.h>
@@ -68,46 +67,26 @@
 		return ENOMEM;
 
-	hw_resource_list_t hw_resources;
-	const int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
+	hw_res_list_parsed_t hw_res;
+	hw_res_list_parsed_init(&hw_res);
+	const int ret =  hw_res_get_list_parsed(parent_sess, &hw_res, 0);
 	async_hangup(parent_sess);
-	if (rc != EOK) {
-		return rc;
+	if (ret != EOK) {
+		return ret;
 	}
 
-	uintptr_t io_address = 0;
-	size_t io_size = 0;
-	bool io_found = false;
+	/* We want one irq and one io range. */
+	if (hw_res.irqs.count != 1 || hw_res.io_ranges.count != 1) {
+		hw_res_list_parsed_clean(&hw_res);
+		return EINVAL;
+	}
 
-	int irq = 0;
-	bool irq_found = false;
+	if (io_reg_address)
+		*io_reg_address = hw_res.io_ranges.ranges[0].address;
+	if (io_reg_size)
+		*io_reg_size = hw_res.io_ranges.ranges[0].size;
+	if (irq_no)
+		*irq_no = hw_res.irqs.irqs[0];
 
-	for (size_t i = 0; i < hw_resources.count; i++) {
-		const hw_resource_t *res = &hw_resources.resources[i];
-		switch (res->type) {
-		case INTERRUPT:
-			irq = res->res.interrupt.irq;
-			irq_found = true;
-			usb_log_debug2("Found interrupt: %d.\n", irq);
-			break;
-		case IO_RANGE:
-			io_address = res->res.io_range.address;
-			io_size = res->res.io_range.size;
-			usb_log_debug2("Found io: %" PRIx64" %zu.\n",
-			    res->res.io_range.address, res->res.io_range.size);
-			io_found = true;
-			break;
-		default:
-			break;
-		}
-	}
-	free(hw_resources.resources);
-
-	if (!io_found || !irq_found)
-		return ENOENT;
-
-	*io_reg_address = io_address;
-	*io_reg_size = io_size;
-	*irq_no = irq;
-
+	hw_res_list_parsed_clean(&hw_res);
 	return EOK;
 }
Index: uspace/drv/bus/usb/uhci/transfer_list.c
===================================================================
--- uspace/drv/bus/usb/uhci/transfer_list.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/uhci/transfer_list.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -184,6 +184,5 @@
 		    uhci_transfer_batch_from_link(current);
 		transfer_list_remove_batch(instance, batch);
-		batch->usb_batch->error = EINTR;
-		uhci_transfer_batch_call_dispose(batch);
+		uhci_transfer_batch_abort(batch);
 	}
 	fibril_mutex_unlock(&instance->guard);
Index: uspace/drv/bus/usb/uhci/uhci.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/uhci/uhci.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -148,6 +148,8 @@
 int device_setup_uhci(ddf_dev_t *device)
 {
-	assert(device);
-	uhci_t *instance = malloc(sizeof(uhci_t));
+	if (!device)
+		return EBADMEM;
+
+	uhci_t *instance = ddf_dev_data_alloc(device, sizeof(uhci_t));
 	if (instance == NULL) {
 		usb_log_error("Failed to allocate OHCI driver.\n");
@@ -158,13 +160,10 @@
 if (ret != EOK) { \
 	if (instance->hc_fun) \
-		instance->hc_fun->ops = NULL; \
 		instance->hc_fun->driver_data = NULL; \
 		ddf_fun_destroy(instance->hc_fun); \
 	if (instance->rh_fun) {\
-		instance->rh_fun->ops = NULL; \
 		instance->rh_fun->driver_data = NULL; \
 		ddf_fun_destroy(instance->rh_fun); \
 	} \
-	device->driver_data = NULL; \
 	usb_log_error(message); \
 	return ret; \
@@ -227,6 +226,4 @@
 	    "Failed to init uhci_hcd: %s.\n", str_error(ret));
 
-	device->driver_data = instance;
-
 #define CHECK_RET_FINI_RETURN(ret, message...) \
 if (ret != EOK) { \
Index: uspace/drv/bus/usb/uhci/uhci_batch.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci_batch.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/uhci/uhci_batch.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -34,4 +34,5 @@
 #include <errno.h>
 #include <str_error.h>
+#include <macros.h>
 
 #include <usb/usb.h>
@@ -45,4 +46,8 @@
 #define DEFAULT_ERROR_COUNT 3
 
+/** Safely destructs uhci_transfer_batch_t structure.
+ *
+ * @param[in] uhci_batch Instance to destroy.
+ */
 static void uhci_transfer_batch_dispose(uhci_transfer_batch_t *uhci_batch)
 {
@@ -54,31 +59,23 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Safely destructs uhci_transfer_batch_t structure
- *
- * @param[in] uhci_batch Instance to destroy.
- */
-void uhci_transfer_batch_call_dispose(uhci_transfer_batch_t *uhci_batch)
+/** Finishes usb_transfer_batch and destroys the structure.
+ *
+ * @param[in] uhci_batch Instance to finish and destroy.
+ */
+void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch)
 {
 	assert(uhci_batch);
 	assert(uhci_batch->usb_batch);
 	usb_transfer_batch_finish(uhci_batch->usb_batch,
-	    uhci_transfer_batch_data_buffer(uhci_batch),
-	    uhci_batch->usb_batch->buffer_size);
+	    uhci_transfer_batch_data_buffer(uhci_batch));
 	uhci_transfer_batch_dispose(uhci_batch);
 }
 /*----------------------------------------------------------------------------*/
+/** Transfer batch setup table. */
 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t);
 /*----------------------------------------------------------------------------*/
 /** Allocate memory and initialize internal data structure.
  *
- * @param[in] fun DDF function to pass to callback.
- * @param[in] ep Communication target
- * @param[in] buffer Data source/destination.
- * @param[in] buffer_size Size of the buffer.
- * @param[in] setup_buffer Setup data source (if not NULL)
- * @param[in] setup_size Size of setup_buffer (should be always 8)
- * @param[in] func_in function to call on inbound transfer completion
- * @param[in] func_out function to call on outbound transfer completion
- * @param[in] arg additional parameter to func_in or func_out
+ * @param[in] usb_batch Pointer to generic USB batch structure.
  * @return Valid pointer if all structures were successfully created,
  * NULL otherwise.
@@ -156,5 +153,5 @@
  * is reached.
  */
-bool uhci_transfer_batch_is_complete(uhci_transfer_batch_t *uhci_batch)
+bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch)
 {
 	assert(uhci_batch);
@@ -200,4 +197,5 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Direction to pid conversion table */
 static const usb_packet_id direction_pids[] = {
 	[USB_DIRECTION_IN] = USB_PID_IN,
@@ -237,6 +235,5 @@
 
 	while (remain_size > 0) {
-		const size_t packet_size =
-		    (remain_size < mps) ? remain_size : mps;
+		const size_t packet_size = min(remain_size, mps);
 
 		const td_t *next_td = (td + 1 < uhci_batch->td_count)
@@ -309,6 +306,5 @@
 
 	while (remain_size > 0) {
-		const size_t packet_size =
-		    (remain_size < mps) ? remain_size : mps;
+		const size_t packet_size = min(remain_size, mps);
 
 		td_init(
Index: uspace/drv/bus/usb/uhci/uhci_batch.h
===================================================================
--- uspace/drv/bus/usb/uhci/uhci_batch.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/uhci/uhci_batch.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -61,7 +61,11 @@
 
 uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *batch);
-void uhci_transfer_batch_call_dispose(uhci_transfer_batch_t *uhci_batch);
-bool uhci_transfer_batch_is_complete(uhci_transfer_batch_t *uhci_batch);
+void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch);
+bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch);
 
+/** Get offset to setup buffer accessible to the HC hw.
+ * @param uhci_batch UHCI batch structure.
+ * @return Pointer to the setup buffer.
+ */
 static inline void * uhci_transfer_batch_setup_buffer(
     const uhci_transfer_batch_t *uhci_batch)
@@ -73,4 +77,8 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Get offset to data buffer accessible to the HC hw.
+ * @param uhci_batch UHCI batch structure.
+ * @return Pointer to the data buffer.
+ */
 static inline void * uhci_transfer_batch_data_buffer(
     const uhci_transfer_batch_t *uhci_batch)
@@ -82,4 +90,22 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Aborts the batch.
+ * Sets error to EINTR and size off transferd data to 0, before finishing the
+ * batch.
+ * @param uhci_batch Batch to abort.
+ */
+static inline void uhci_transfer_batch_abort(uhci_transfer_batch_t *uhci_batch)
+{
+	assert(uhci_batch);
+	assert(uhci_batch->usb_batch);
+	uhci_batch->usb_batch->error = EINTR;
+	uhci_batch->usb_batch->transfered_size = 0;
+	uhci_transfer_batch_finish_dispose(uhci_batch);
+}
+/*----------------------------------------------------------------------------*/
+/** Linked list conversion wrapper.
+ * @param l Linked list link.
+ * @return Pointer to the uhci batch structure.
+ */
 static inline uhci_transfer_batch_t *uhci_transfer_batch_from_link(link_t *l)
 {
Index: uspace/drv/bus/usb/uhci/utils/malloc32.h
===================================================================
--- uspace/drv/bus/usb/uhci/utils/malloc32.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/uhci/utils/malloc32.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -98,11 +98,9 @@
 static inline void * get_page(void)
 {
-	void *free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE);
-	if (free_address == 0)
+	void *address = as_area_create((void *) -1, UHCI_REQUIRED_PAGE_SIZE,
+	    AS_AREA_READ | AS_AREA_WRITE);
+	if (address == (void *) -1)
 		return NULL;
-	void *address = as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
-		  AS_AREA_READ | AS_AREA_WRITE);
-	if (address != free_address)
-		return NULL;
+	
 	return address;
 }
Index: uspace/drv/bus/usb/uhcirh/main.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/main.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/uhcirh/main.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -36,5 +36,5 @@
 #include <ddf/driver.h>
 #include <devman.h>
-#include <device/hw_res.h>
+#include <device/hw_res_parsed.h>
 #include <errno.h>
 #include <str_error.h>
@@ -136,5 +136,5 @@
 {
 	assert(dev);
-	
+
 	async_sess_t *parent_sess =
 	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
@@ -142,37 +142,25 @@
 	if (!parent_sess)
 		return ENOMEM;
-	
-	hw_resource_list_t hw_resources;
-	const int ret = hw_res_get_resource_list(parent_sess, &hw_resources);
+
+	hw_res_list_parsed_t hw_res;
+	hw_res_list_parsed_init(&hw_res);
+	const int ret =  hw_res_get_list_parsed(parent_sess, &hw_res, 0);
+	async_hangup(parent_sess);
 	if (ret != EOK) {
-		async_hangup(parent_sess);
 		return ret;
 	}
-	
-	uintptr_t io_address = 0;
-	size_t io_size = 0;
-	bool io_found = false;
-	
-	size_t i = 0;
-	for (; i < hw_resources.count; i++) {
-		hw_resource_t *res = &hw_resources.resources[i];
-		if (res->type == IO_RANGE) {
-			io_address = res->res.io_range.address;
-			io_size = res->res.io_range.size;
-			io_found = true;
-		}
-	
+
+	if (hw_res.io_ranges.count != 1) {
+		hw_res_list_parsed_clean(&hw_res);
+		return EINVAL;
 	}
-	async_hangup(parent_sess);
-	
-	if (!io_found)
-		return ENOENT;
-	
+
 	if (io_reg_address != NULL)
-		*io_reg_address = io_address;
-	
+		*io_reg_address = hw_res.io_ranges.ranges[0].address;
+
 	if (io_reg_size != NULL)
-		*io_reg_size = io_size;
-	
+		*io_reg_size = hw_res.io_ranges.ranges[0].size;
+
+	hw_res_list_parsed_clean(&hw_res);
 	return EOK;
 }
Index: uspace/drv/bus/usb/uhcirh/port.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/port.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/uhcirh/port.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -260,5 +260,4 @@
 {
 	assert(port);
-	assert(usb_hc_connection_is_opened(&port->hc_connection));
 
 	usb_log_debug("%s: Detected new device.\n", port->id_string);
@@ -314,6 +313,6 @@
 
 	/* Driver stopped, free used address */
-	ret = usb_hc_unregister_device(&port->hc_connection,
-	    port->attached_device.address);
+	ret = usb_hub_unregister_device(&port->hc_connection,
+	    &port->attached_device);
 	if (ret != EOK) {
 		usb_log_error("%s: Failed to unregister address of removed "
Index: uspace/drv/bus/usb/usbhub/port.c
===================================================================
--- uspace/drv/bus/usb/usbhub/port.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/usbhub/port.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -288,21 +288,9 @@
 	port->attached_device.fun = NULL;
 
-	ret = usb_hc_connection_open(&hub->connection);
-	if (ret == EOK) {
-		ret = usb_hc_unregister_device(&hub->connection,
-		    port->attached_device.address);
-		if (ret != EOK) {
-			usb_log_warning("Failed to unregister address of the "
-			    "removed device: %s.\n", str_error(ret));
-		}
-		ret = usb_hc_connection_close(&hub->connection);
-		if (ret != EOK) {
-			usb_log_warning("Failed to close hc connection %s.\n",
-			    str_error(ret));
-		}
-
-	} else {
-		usb_log_warning("Failed to open hc connection %s.\n",
-		    str_error(ret));
+	ret = usb_hub_unregister_device(&hub->usb_device->hc_conn,
+	    &port->attached_device);
+	if (ret != EOK) {
+		usb_log_warning("Failed to unregister address of the "
+		    "removed device: %s.\n", str_error(ret));
 	}
 
@@ -438,5 +426,5 @@
 
 	const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
-	    &data->hub->connection, data->speed, enable_port_callback,
+	    &data->hub->usb_device->hc_conn, data->speed, enable_port_callback,
 	    data->port, &new_address, NULL, NULL, &child_fun);
 
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -99,10 +99,8 @@
 	fibril_condvar_initialize(&hub_dev->pending_ops_cv);
 
-	/* Create hc connection */
-	usb_log_debug("Initializing USB wire abstraction.\n");
-	int opResult = usb_hc_connection_initialize_from_device(
-	    &hub_dev->connection, hub_dev->usb_device->ddf_dev);
-	if (opResult != EOK) {
-		usb_log_error("Could not initialize connection to device: %s\n",
+
+	int opResult = usb_pipe_start_long_transfer(&usb_dev->ctrl_pipe);
+	if (opResult != EOK) {
+		usb_log_error("Failed to start long ctrl pipe transfer: %s\n",
 		    str_error(opResult));
 		return opResult;
@@ -112,4 +110,5 @@
 	opResult = usb_set_first_configuration(usb_dev);
 	if (opResult != EOK) {
+		usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
 		usb_log_error("Could not set hub configuration: %s\n",
 		    str_error(opResult));
@@ -120,4 +119,5 @@
 	opResult = usb_hub_process_hub_specific_info(hub_dev);
 	if (opResult != EOK) {
+		usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
 		usb_log_error("Could process hub specific info, %s\n",
 		    str_error(opResult));
@@ -130,4 +130,5 @@
 	    fun_exposed, HUB_FNC_NAME);
 	if (hub_dev->hub_fun == NULL) {
+		usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
 		usb_log_error("Failed to create hub function.\n");
 		return ENOMEM;
@@ -137,4 +138,5 @@
 	opResult = ddf_fun_bind(hub_dev->hub_fun);
 	if (opResult != EOK) {
+		usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
 		usb_log_error("Failed to bind hub function: %s.\n",
 		   str_error(opResult));
@@ -148,4 +150,5 @@
 	    usb_hub_polling_terminated_callback, hub_dev);
 	if (opResult != EOK) {
+		usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
 		/* Function is already bound */
 		ddf_fun_unbind(hub_dev->hub_fun);
@@ -159,4 +162,5 @@
 	    hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);
 
+	usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
 	return EOK;
 }
Index: uspace/drv/bus/usb/usbhub/usbhub.h
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/usbhub/usbhub.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -57,6 +57,4 @@
 	/** Port structures, one for each port */
 	usb_hub_port_t *ports;
-	/** Connection to hcd */
-	usb_hc_connection_t connection;
 	/** Generic usb device data*/
 	usb_device_t *usb_device;
Index: uspace/drv/bus/usb/usbmast/main.c
===================================================================
--- uspace/drv/bus/usb/usbmast/main.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/usbmast/main.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -300,13 +300,11 @@
 		return;
 	}
-
-	comm_buf = as_get_mappable_page(comm_size);
-	if (comm_buf == NULL) {
+	
+	(void) async_share_out_finalize(callid, &comm_buf);
+	if (comm_buf == (void *) -1) {
 		async_answer_0(callid, EHANGUP);
 		return;
 	}
-
-	(void) async_share_out_finalize(callid, comm_buf);
-
+	
 	mfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
 
Index: uspace/drv/bus/usb/usbmid/main.c
===================================================================
--- uspace/drv/bus/usb/usbmid/main.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/usbmid/main.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -53,9 +53,5 @@
 	usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name);
 
-	usb_pipe_start_long_transfer(&dev->ctrl_pipe);
-
-	bool accept = usbmid_explore_device(dev);
-
-	usb_pipe_end_long_transfer(&dev->ctrl_pipe);
+	const bool accept = usbmid_explore_device(dev);
 
 	if (!accept) {
Index: uspace/drv/bus/usb/vhc/hub.c
===================================================================
--- uspace/drv/bus/usb/vhc/hub.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/bus/usb/vhc/hub.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -107,6 +107,5 @@
 
 	usb_hc_connection_t hc_conn;
-	rc = usb_hc_connection_initialize(&hc_conn, hc_dev->handle);
-	assert(rc == EOK);
+	usb_hc_connection_initialize(&hc_conn, hc_dev->handle);
 
 	rc = usb_hc_connection_open(&hc_conn);
Index: uspace/drv/infrastructure/rootmac/rootmac.c
===================================================================
--- uspace/drv/infrastructure/rootmac/rootmac.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/infrastructure/rootmac/rootmac.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -161,6 +161,6 @@
 
 static hw_res_ops_t fun_hw_res_ops = {
-	&rootmac_get_resources,
-	&rootmac_enable_interrupt
+   	.get_resource_list = &rootmac_get_resources,
+	.enable_interrupt = &rootmac_enable_interrupt
 };
 
Index: uspace/drv/infrastructure/rootpc/rootpc.c
===================================================================
--- uspace/drv/infrastructure/rootpc/rootpc.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/infrastructure/rootpc/rootpc.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -109,6 +109,6 @@
 
 static hw_res_ops_t fun_hw_res_ops = {
-	&rootpc_get_resources,
-	&rootpc_enable_interrupt
+	.get_resource_list = &rootpc_get_resources,
+	.enable_interrupt = &rootpc_enable_interrupt,
 };
 
Index: uspace/drv/nic/rtl8139/defs.c
===================================================================
--- uspace/drv/nic/rtl8139/defs.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/nic/rtl8139/defs.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -27,5 +27,5 @@
  */
 
-#include "rtl8139_defs.h"
+#include "defs.h"
 
 const char* model_names[RTL8139_VER_COUNT] = {
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/nic/rtl8139/driver.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -33,9 +33,9 @@
 #include <libarch/ddi.h>
 #include <libarch/barrier.h>
-#include <nlog.h>
-
-#include <dma.h>
+
+#include <as.h>
+#include <ddf/log.h>
 #include <ddf/interrupt.h>
-#include <devman.h>
+#include <io/log.h>
 #include <nic.h>
 #include <packet_client.h>
@@ -50,7 +50,7 @@
 #include <str.h>
 
-#include "rtl8139_defs.h"
-#include "rtl8139_driver.h"
-#include "rtl8139_general.h"
+#include "defs.h"
+#include "driver.h"
+#include "general.h"
 
 /** Global mutex for work with shared irq structure */
@@ -164,5 +164,5 @@
 	    (RXBUF_SIZE_FLAGS << RCR_RBLEN_SHIFT);
 	
-	nlog_debug("Rewriting rcr: %x -> %x", pio_read_32(rtl8139->io_port + RCR),
+	ddf_msg(LVL_DEBUG, "Rewriting rcr: %x -> %x", pio_read_32(rtl8139->io_port + RCR),
 	    rcr);
 
@@ -373,9 +373,9 @@
 static ddf_dev_ops_t rtl8139_dev_ops;
 
-static int rtl8139_add_device(ddf_dev_t *dev);
+static int rtl8139_dev_add(ddf_dev_t *dev);
 
 /** Basic driver operations for RTL8139 driver */
 static driver_ops_t rtl8139_driver_ops = {
-	.add_device = &rtl8139_add_device,
+	.dev_add = &rtl8139_dev_add,
 };
 
@@ -409,5 +409,5 @@
 	rtl8139_t *rtl8139 = nic_get_specific(nic_data);
 	assert(rtl8139);
-	nlog_debug("Sending packet");
+	ddf_msg(LVL_DEBUG, "Sending packet");
 
 	/* Get the packet data and check if it can be send */
@@ -418,5 +418,5 @@
 
 	if ((packet_length > RTL8139_PACKET_MAX_LENGTH) || !packet_data) {
-		nlog_error("Write packet length error: data %p, length %z", 
+		ddf_msg(LVL_ERROR, "Write packet length error: data %p, length %z", 
 		    packet_data, packet_length);
 		nic_report_send_error(rtl8139->nic_data, NIC_SEC_OTHER, 1);
@@ -527,5 +527,5 @@
 	nic_frame_t *frame = nic_alloc_frame(nic_data, packet_size);
 	if (! frame) {
-		nlog_error("Can not allocate frame for received packet.");
+		ddf_msg(LVL_ERROR, "Can not allocate frame for received packet.");
 		return NULL;
 	}
@@ -533,5 +533,5 @@
 	void *packet_data = packet_suffix(frame->packet, packet_size);
 	if (!packet_data) {
-		nlog_error("Can not get the packet suffix.");
+		ddf_msg(LVL_ERROR, "Can not get the packet suffix.");
 		nic_release_frame(nic_data, frame);
 		return NULL;
@@ -564,5 +564,5 @@
 	pio_write_32(rtl8139->io_port + CAPR, 0);
 	pio_write_32(rtl8139->io_port + RBSTART, 
-	    PTR2U32(rtl8139->rx_buff.physical));
+	    PTR2U32(rtl8139->rx_buff_phys));
 
 	write_barrier();
@@ -588,7 +588,7 @@
 	nic_frame_list_t *frames = nic_alloc_frame_list();
 	if (!frames)
-		nlog_error("Can not allocate frame list for received packets.");
-
-	void *rx_buffer = rtl8139->rx_buff.virtual;
+		ddf_msg(LVL_ERROR, "Can not allocate frame list for received packets.");
+
+	void *rx_buffer = rtl8139->rx_buff_virt;
 
 	/* where to start reading */
@@ -620,5 +620,5 @@
 		if (size == RTL8139_EARLY_SIZE) {
 			/* The packet copying is still in progress, break receiving */
-			nlog_debug("Early threshold reached, not completely coppied");
+			ddf_msg(LVL_DEBUG, "Early threshold reached, not completely coppied");
 			break;
 		}
@@ -626,5 +626,5 @@
 		/* Check if the header is valid, otherwise we are lost in the buffer */
 		if (size == 0 || size > RTL8139_PACKET_MAX_LENGTH) {
-			nlog_error("Receiver error -> receiver reset (size: %4"PRIu16", "
+			ddf_msg(LVL_ERROR, "Receiver error -> receiver reset (size: %4"PRIu16", "
 			    "header 0x%4"PRIx16". Offset: %zu)", size, packet_header, 
 			    rx_offset);
@@ -632,5 +632,5 @@
 		}
 		if (size < RTL8139_RUNT_MAX_SIZE && !(rcs & RSR_RUNT)) {
-			nlog_error("Receiver error -> receiver reset (%"PRIx16")", size);
+			ddf_msg(LVL_ERROR, "Receiver error -> receiver reset (%"PRIx16")", size);
 			goto rx_err;
 		}
@@ -801,5 +801,5 @@
 	pio_write_32(rtl8139->io_port + TIMERINT, timer_val);
 	pio_write_32(rtl8139->io_port + TCTR, 0x0);
-	nlog_debug("rtl8139 timer: %"PRIu32"\treceive: %d", timer_val, receive);
+	ddf_msg(LVL_DEBUG, "rtl8139 timer: %"PRIu32"\treceive: %d", timer_val, receive);
 	return receive;
 }
@@ -925,5 +925,5 @@
 	/* Write transmittion buffer addresses */
 	for(i = 0; i < TX_BUFF_COUNT; ++i) {
-		uint32_t addr = PTR2U32(rtl8139->tx_buff_mem.physical + i*TX_BUFF_SIZE);
+		uint32_t addr = PTR2U32(rtl8139->tx_buff_phys + i*TX_BUFF_SIZE);
 		pio_write_32(io_base + TSAD0 + 4*i, addr);
 	}
@@ -932,5 +932,5 @@
 	nic_set_tx_busy(rtl8139->nic_data, 0);
 
-	pio_write_32(io_base + RBSTART, PTR2U32(rtl8139->rx_buff.physical));
+	pio_write_32(io_base + RBSTART, PTR2U32(rtl8139->rx_buff_phys));
 
 	/* Enable transmitter and receiver */
@@ -949,5 +949,5 @@
 {
 	assert(nic_data);
-	nlog_info("Activating device");
+	ddf_msg(LVL_NOTE, "Activating device");
 
 	rtl8139_t *rtl8139 = nic_get_specific(nic_data);
@@ -962,5 +962,5 @@
 	nic_enable_interrupt(nic_data, rtl8139->irq);
 
-	nlog_debug("Device activated, interrupt %d registered", rtl8139->irq);
+	ddf_msg(LVL_DEBUG, "Device activated, interrupt %d registered", rtl8139->irq);
 	return EOK;
 }
@@ -1079,22 +1079,22 @@
 
 	if (hw_resources->irqs.count != 1) {
-		nlog_error("%s device: unexpected irq count", dev->name);
+		ddf_msg(LVL_ERROR, "%s device: unexpected irq count", dev->name);
 		return EINVAL;
 	};
 	if (hw_resources->io_ranges.count != 1) {
-		nlog_error("%s device: unexpected io ranges count", dev->name);
+		ddf_msg(LVL_ERROR, "%s device: unexpected io ranges count", dev->name);
 		return EINVAL;
 	}
 
 	rtl8139->irq = hw_resources->irqs.irqs[0];
-	nlog_debug("%s device: irq 0x%x assigned", dev->name, rtl8139->irq);
+	ddf_msg(LVL_DEBUG, "%s device: irq 0x%x assigned", dev->name, rtl8139->irq);
 
 	rtl8139->io_addr = IOADDR_TO_PTR(hw_resources->io_ranges.ranges[0].address);
 	if (hw_resources->io_ranges.ranges[0].size < RTL8139_IO_SIZE) {
-		nlog_error("i/o range assigned to the device "
+		ddf_msg(LVL_ERROR, "i/o range assigned to the device "
 		    "%s is too small.", dev->name);
 		return EINVAL;
 	}
-	nlog_debug("%s device: i/o addr %p assigned.", dev->name, rtl8139->io_addr);
+	ddf_msg(LVL_DEBUG, "%s device: i/o addr %p assigned.", dev->name, rtl8139->io_addr);
 
 	return EOK;
@@ -1142,22 +1142,20 @@
 static int rtl8139_buffers_create(rtl8139_t *rtl8139)
 {
-	assert(rtl8139);
 	size_t i = 0;
 	int rc;
 
-	nlog_debug("Creating buffers");
-
-	rtl8139->tx_buff_mem.size = TX_PAGES;
-	rtl8139->tx_buff_mem.mapping_flags = AS_AREA_WRITE;
-	rc = dma_allocate_anonymous(&rtl8139->tx_buff_mem, DMA_32_BITS);
+	ddf_msg(LVL_DEBUG, "Creating buffers");
+
+	rc = dmamem_map_anonymous(TX_PAGES * PAGE_SIZE, AS_AREA_WRITE, 0,
+	    &rtl8139->tx_buff_phys, &rtl8139->tx_buff_virt);
 	if (rc != EOK) {
-		nlog_error("Can not allocate transmitter buffers.");
+		ddf_msg(LVL_ERROR, "Can not allocate transmitter buffers.");
 		goto err_tx_alloc;
 	}
 
-	for(i = 0; i < TX_BUFF_COUNT; ++i)
-		rtl8139->tx_buff[i] = rtl8139->tx_buff_mem.virtual + i * TX_BUFF_SIZE;
-
-	nlog_debug("The transmittion buffers allocated");
+	for (i = 0; i < TX_BUFF_COUNT; ++i)
+		rtl8139->tx_buff[i] = rtl8139->tx_buff_virt + i * TX_BUFF_SIZE;
+
+	ddf_msg(LVL_DEBUG, "The transmittion buffers allocated");
 
 	/* Use the first buffer for next transmittion */
@@ -1166,20 +1164,19 @@
 
 	/* Allocate buffer for receiver */
-	size_t rx_pages = ALIGN_UP(RxBUF_TOT_LENGTH, PAGE_SIZE) / PAGE_SIZE;
-	nlog_debug("Allocating receiver buffer of the size %zd pages", rx_pages);
-
-	rtl8139->rx_buff.size = rx_pages;
-	rtl8139->rx_buff.mapping_flags = AS_AREA_READ;
-	rc = dma_allocate_anonymous(&rtl8139->rx_buff, DMA_32_BITS);
-	if( rc != EOK ) {
-		nlog_error("Can not allocate receiver buffer.");
+	ddf_msg(LVL_DEBUG, "Allocating receiver buffer of the size %zu bytes",
+	    RxBUF_TOT_LENGTH);
+
+	rc = dmamem_map_anonymous(RxBUF_TOT_LENGTH, AS_AREA_READ, 0,
+	    &rtl8139->rx_buff_phys, &rtl8139->rx_buff_virt);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Can not allocate receive buffer.");
 		goto err_rx_alloc;
 	}
-	nlog_debug("The buffers created");
+	ddf_msg(LVL_DEBUG, "The buffers created");
 
 	return EOK;
 
 err_rx_alloc:
-	dma_free(&rtl8139->tx_buff_mem);
+	dmamem_unmap_anonymous(&rtl8139->tx_buff_virt);
 err_tx_alloc:
 	return rc;
@@ -1194,27 +1191,27 @@
 static int rtl8139_device_initialize(ddf_dev_t *dev)
 {
-	nlog_debug("rtl8139_dev_initialize %s", dev->name);
+	ddf_msg(LVL_DEBUG, "rtl8139_dev_initialize %s", dev->name);
 
 	int ret = EOK;
 
-	nlog_debug("rtl8139: creating device data");
+	ddf_msg(LVL_DEBUG, "rtl8139: creating device data");
 
 	/* Allocate driver data for the device. */
 	rtl8139_t *rtl8139 = rtl8139_create_dev_data(dev);
 	if (rtl8139 == NULL) {
-		nlog_error("Not enough memory for initializing %s.", dev->name);
+		ddf_msg(LVL_ERROR, "Not enough memory for initializing %s.", dev->name);
 		return ENOMEM;
 	}
 
-	nlog_debug("rtl8139: dev_data created");
+	ddf_msg(LVL_DEBUG, "rtl8139: dev_data created");
 
 	/* Obtain and fill hardware resources info and connect to parent */
 	ret = rtl8139_get_resource_info(dev);
 	if (ret != EOK) {
-		nlog_error("Can not obatin hw resources information");
+		ddf_msg(LVL_ERROR, "Can not obatin hw resources information");
 		goto failed;
 	}
 
-	nlog_debug("rtl8139: resource_info obtained");
+	ddf_msg(LVL_DEBUG, "rtl8139: resource_info obtained");
 
 	/* Allocate DMA buffers */
@@ -1231,9 +1228,9 @@
 	rtl8139->rcr_data.rcr_base = (0x8 << RCR_ERTH_SHIFT);
 
-	nlog_debug("The device is initialized");
+	ddf_msg(LVL_DEBUG, "The device is initialized");
 	return ret;
 
 failed:
-	nlog_error("The device initialization failed");
+	ddf_msg(LVL_ERROR, "The device initialization failed");
 	rtl8139_dev_cleanup(dev);
 	return ret;
@@ -1248,5 +1245,5 @@
 static int rtl8139_pio_enable(ddf_dev_t *dev)
 {
-	nlog_debug(NAME ": rtl8139_pio_enable %s", dev->name);
+	ddf_msg(LVL_DEBUG, NAME ": rtl8139_pio_enable %s", dev->name);
 
 	rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_dev(dev));
@@ -1254,5 +1251,5 @@
 	/* Gain control over port's registers. */
 	if (pio_enable(rtl8139->io_addr, RTL8139_IO_SIZE, &rtl8139->io_port)) {
-		nlog_error("Cannot gain the port %lx for device %s.", rtl8139->io_addr,
+		ddf_msg(LVL_ERROR, "Cannot gain the port %lx for device %s.", rtl8139->io_addr,
 		    dev->name);
 		return EADDRNOTAVAIL;
@@ -1282,5 +1279,5 @@
 		if (rtl8139_versions[i].hwverid == hwverid) {
 			rtl8139->hw_version = rtl8139_versions[i].ver_id;
-			nlog_info("HW version found: index %zu, ver_id %d (%s)", i,
+			ddf_msg(LVL_NOTE, "HW version found: index %zu, ver_id %d (%s)", i,
 			    rtl8139_versions[i].ver_id, model_names[rtl8139->hw_version]);
 		}
@@ -1296,8 +1293,8 @@
  * @return EOK if added successfully, negative error code otherwise
  */
-int rtl8139_add_device(ddf_dev_t *dev)
+int rtl8139_dev_add(ddf_dev_t *dev)
 {
 	assert(dev);
-	nlog_info("RTL8139_add_device %s (handle = %d)", dev->name, dev->handle);
+	ddf_msg(LVL_NOTE, "RTL8139_dev_add %s (handle = %d)", dev->name, dev->handle);
 
 	/* Init device structure for rtl8139 */
@@ -1330,5 +1327,5 @@
 	rc = nic_connect_to_services(nic_data);
 	if (rc != EOK) {
-		nlog_error("Failed to connect to services", rc);
+		ddf_msg(LVL_ERROR, "Failed to connect to services", rc);
 		goto err_irq;
 	}
@@ -1336,9 +1333,9 @@
 	rc = nic_register_as_ddf_fun(nic_data, &rtl8139_dev_ops);
 	if (rc != EOK) {
-		nlog_error("Failed to register as DDF function - error %d", rc);
+		ddf_msg(LVL_ERROR, "Failed to register as DDF function - error %d", rc);
 		goto err_irq;
 	}
 
-	nlog_info("The %s device has been successfully initialized.",
+	ddf_msg(LVL_NOTE, "The %s device has been successfully initialized.",
 	    dev->name);
 
@@ -1581,5 +1578,5 @@
 
 	if (allow_send && time > 0) {
-		nlog_warning("Time setting is not supported in set_pause method.");
+		ddf_msg(LVL_WARN, "Time setting is not supported in set_pause method.");
 	}
 	return EOK;
@@ -2121,5 +2118,5 @@
 		pio_write_32(rtl8139->io_port + TCTR, 0);
 
-		nlog_debug("Periodic mode. Interrupt mask %"PRIx16", poll.full_skips %"
+		ddf_msg(LVL_DEBUG, "Periodic mode. Interrupt mask %"PRIx16", poll.full_skips %"
 		    PRIu32", last timer %"PRIu32".", rtl8139->int_mask, 
 		    rtl8139->poll_timer.full_skips, rtl8139->poll_timer.last_val);
@@ -2168,6 +2165,6 @@
 		&rtl8139_driver_ops, &rtl8139_dev_ops, &rtl8139_nic_iface);
 
-	nlog_set_min_severity(DEBUG);
-	nlog_info("HelenOS RTL8139 driver started");
+	ddf_log_init(NAME, LVL_ERROR);
+	ddf_msg(LVL_NOTE, "HelenOS RTL8139 driver started");
 	return ddf_driver_main(&rtl8139_driver);
 }
Index: uspace/drv/nic/rtl8139/driver.h
===================================================================
--- uspace/drv/nic/rtl8139/driver.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/nic/rtl8139/driver.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -30,9 +30,8 @@
 #define RTL8139_DRIVER_H_
 
-#include "rtl8139_defs.h"
-#include "rtl8139_general.h"
+#include "defs.h"
+#include "general.h"
 #include <sys/types.h>
 #include <stdint.h>
-#include <dma.h>
 
 /** The driver name */
@@ -97,5 +96,7 @@
 	 *  Each buffer takes 2kB
 	 */
-	dma_mem_t tx_buff_mem;
+	void *tx_buff_phys;
+	void *tx_buff_virt;
+
 	/** Virtual adresses of the Tx buffers */
 	void *tx_buff[TX_BUFF_COUNT];
@@ -112,5 +113,6 @@
 
 	/** Buffer for receiving packets */
-	dma_mem_t rx_buff;
+	void *rx_buff_phys;
+	void *rx_buff_virt;
 
 	/** Receiver control register data */
Index: uspace/drv/nic/rtl8139/general.c
===================================================================
--- uspace/drv/nic/rtl8139/general.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/drv/nic/rtl8139/general.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -32,5 +32,5 @@
  */
 
-#include "rtl8139_general.h"
+#include "general.h"
 
 #include <mem.h>
Index: uspace/lib/c/generic/as.c
===================================================================
--- uspace/lib/c/generic/as.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/generic/as.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -45,15 +45,18 @@
 /** Create address space area.
  *
- * @param address Virtual address where to place new address space area.
- * @param size    Size of the area.
- * @param flags   Flags describing type of the area.
+ * @param base  Starting virtual address of the area.
+ *              If set to (void *) -1, the kernel finds
+ *              a mappable area.
+ * @param size  Size of the area.
+ * @param flags Flags describing type of the area.
  *
- * @return address on success, (void *) -1 otherwise.
+ * @return Starting virtual address of the created area on success.
+ * @return (void *) -1 otherwise.
  *
  */
-void *as_area_create(void *address, size_t size, unsigned int flags)
+void *as_area_create(void *base, size_t size, unsigned int flags)
 {
-	return (void *) __SYSCALL3(SYS_AS_AREA_CREATE, (sysarg_t) address,
-	    (sysarg_t) size, (sysarg_t) flags);
+	return (void *) __SYSCALL4(SYS_AS_AREA_CREATE, (sysarg_t) base,
+	    (sysarg_t) size, (sysarg_t) flags, (sysarg_t) __entry);
 }
 
@@ -102,17 +105,4 @@
 }
 
-/** Return pointer to unmapped address space area
- *
- * @param size Requested size of the allocation.
- *
- * @return Pointer to the beginning of unmapped address space area.
- *
- */
-void *as_get_mappable_page(size_t size)
-{
-	return (void *) __SYSCALL2(SYS_AS_GET_UNMAPPED_AREA,
-	    (sysarg_t) __entry, (sysarg_t) size);
-}
-
 /** Find mapping to physical address.
  *
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/generic/async.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -1998,25 +1998,27 @@
  *
  * @param exch  Exchange for sending the message.
- * @param dst   Destination address space area base.
  * @param size  Size of the destination address space area.
  * @param arg   User defined argument.
  * @param flags Storage for the received flags. Can be NULL.
+ * @param dst   Destination address space area base. Cannot be NULL.
  *
  * @return Zero on success or a negative error code from errno.h.
  *
  */
-int async_share_in_start(async_exch_t *exch, void *dst, size_t size,
-    sysarg_t arg, unsigned int *flags)
+int async_share_in_start(async_exch_t *exch, size_t size, sysarg_t arg,
+    unsigned int *flags, void **dst)
 {
 	if (exch == NULL)
 		return ENOENT;
 	
-	sysarg_t tmp_flags;
-	int res = async_req_3_2(exch, IPC_M_SHARE_IN, (sysarg_t) dst,
-	    (sysarg_t) size, arg, NULL, &tmp_flags);
+	sysarg_t _flags = 0;
+	sysarg_t _dst = (sysarg_t) -1;
+	int res = async_req_2_4(exch, IPC_M_SHARE_IN, (sysarg_t) size,
+	    arg, NULL, &_flags, NULL, &_dst);
 	
 	if (flags)
-		*flags = (unsigned int) tmp_flags;
-	
+		*flags = (unsigned int) _flags;
+	
+	*dst = (void *) _dst;
 	return res;
 }
@@ -2047,5 +2049,5 @@
 		return false;
 	
-	*size = (size_t) IPC_GET_ARG2(data);
+	*size = (size_t) IPC_GET_ARG1(data);
 	return true;
 }
@@ -2053,5 +2055,5 @@
 /** Wrapper for answering the IPC_M_SHARE_IN calls using the async framework.
  *
- * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
+ * This wrapper only makes it more comfortable to answer IPC_M_SHARE_IN
  * calls so that the user doesn't have to remember the meaning of each IPC
  * argument.
@@ -2131,5 +2133,5 @@
  *
  */
-int async_share_out_finalize(ipc_callid_t callid, void *dst)
+int async_share_out_finalize(ipc_callid_t callid, void **dst)
 {
 	return ipc_share_out_finalize(callid, dst);
Index: uspace/lib/c/generic/ddi.c
===================================================================
--- uspace/lib/c/generic/ddi.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/generic/ddi.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -45,4 +45,5 @@
 #include <align.h>
 #include <libarch/config.h>
+#include "private/libc.h"
 
 /** Return unique device number.
@@ -61,7 +62,7 @@
  *
  * @param phys  Physical address of the starting frame.
- * @param virt  Virtual address of the starting page.
  * @param pages Number of pages to map.
  * @param flags Flags for the new address space area.
+ * @param virt  Virtual address of the starting page.
  *
  * @return EOK on success
@@ -72,8 +73,8 @@
  *
  */
-int physmem_map(void *phys, void *virt, size_t pages, unsigned int flags)
+int physmem_map(void *phys, size_t pages, unsigned int flags, void **virt)
 {
-	return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) phys,
-	    (sysarg_t) virt, pages, flags);
+	return __SYSCALL5(SYS_PHYSMEM_MAP, (sysarg_t) phys,
+	    pages, flags, (sysarg_t) virt, (sysarg_t) __entry);
 }
 
@@ -81,7 +82,7 @@
     unsigned int flags, void **phys)
 {
-	return (int) __SYSCALL5(SYS_DMAMEM_MAP, (sysarg_t) virt,
-	    (sysarg_t) size, (sysarg_t) map_flags, (sysarg_t) flags,
-	    (sysarg_t) phys);
+	return (int) __SYSCALL6(SYS_DMAMEM_MAP, (sysarg_t) size,
+	    (sysarg_t) map_flags, (sysarg_t) flags & ~DMAMEM_FLAGS_ANONYMOUS,
+	    (sysarg_t) phys, (sysarg_t) virt, 0);
 }
 
@@ -89,16 +90,12 @@
     unsigned int flags, void **phys, void **virt)
 {
-	*virt = as_get_mappable_page(size);
-	if (*virt == NULL)
-		return ENOMEM;
-	
-	return dmamem_map(*virt, size, map_flags,
-	    flags | DMAMEM_FLAGS_ANONYMOUS, phys);
+	return (int) __SYSCALL6(SYS_DMAMEM_MAP, (sysarg_t) size,
+	    (sysarg_t) map_flags, (sysarg_t) flags | DMAMEM_FLAGS_ANONYMOUS,
+	    (sysarg_t) phys, (sysarg_t) virt, (sysarg_t) __entry);
 }
 
-int dmamem_unmap(void *virt, size_t size, unsigned int flags)
+int dmamem_unmap(void *virt, size_t size)
 {
-	return __SYSCALL3(SYS_DMAMEM_UNMAP, (sysarg_t) virt, (sysarg_t) size,
-	    (sysarg_t) flags);
+	return __SYSCALL3(SYS_DMAMEM_UNMAP, (sysarg_t) virt, (sysarg_t) size, 0);
 }
 
@@ -138,30 +135,33 @@
  * @param pio_addr I/O start address.
  * @param size     Size of the I/O region.
- * @param use_addr Address where the final address for
- *                 application's PIO will be stored.
+ * @param virt     Virtual address for application's
+ *                 PIO operations.
  *
- * @return Zero on success or negative error code.
+ * @return EOK on success.
+ * @return Negative error code on failure.
  *
  */
-int pio_enable(void *pio_addr, size_t size, void **use_addr)
+int pio_enable(void *pio_addr, size_t size, void **virt)
 {
-	void *phys;
-	void *virt;
-	size_t offset;
-	unsigned int pages;
-	
 #ifdef IO_SPACE_BOUNDARY
 	if (pio_addr < IO_SPACE_BOUNDARY) {
-		*use_addr = pio_addr;
+		*virt = pio_addr;
 		return iospace_enable(task_get_id(), pio_addr, size);
 	}
 #endif
 	
-	phys = (void *) ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
-	offset = pio_addr - phys;
-	pages = ALIGN_UP(offset + size, PAGE_SIZE) >> PAGE_WIDTH;
-	virt = as_get_mappable_page(pages << PAGE_WIDTH);
-	*use_addr = virt + offset;
-	return physmem_map(phys, virt, pages, AS_AREA_READ | AS_AREA_WRITE);
+	void *phys_frame =
+	    (void *) ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
+	size_t offset = pio_addr - phys_frame;
+	size_t pages = SIZE2PAGES(offset + size);
+	
+	void *virt_page;
+	int rc = physmem_map(phys_frame, pages,
+	    AS_AREA_READ | AS_AREA_WRITE, &virt_page);
+	if (rc != EOK)
+		return rc;
+	
+	*virt = virt_page + offset;
+	return EOK;
 }
 
@@ -176,7 +176,7 @@
  *
  */
-int register_irq(int inr, int devno, int method, irq_code_t *ucode)
+int irq_register(int inr, int devno, int method, irq_code_t *ucode)
 {
-	return __SYSCALL4(SYS_REGISTER_IRQ, inr, devno, method,
+	return __SYSCALL4(SYS_IRQ_REGISTER, inr, devno, method,
 	    (sysarg_t) ucode);
 }
@@ -190,7 +190,7 @@
  *
  */
-int unregister_irq(int inr, int devno)
+int irq_unregister(int inr, int devno)
 {
-	return __SYSCALL2(SYS_UNREGISTER_IRQ, inr, devno);
+	return __SYSCALL2(SYS_IRQ_UNREGISTER, inr, devno);
 }
 
Index: uspace/lib/c/generic/elf/elf_load.c
===================================================================
--- uspace/lib/c/generic/elf/elf_load.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/generic/elf/elf_load.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -364,9 +364,9 @@
 	 * and writeable.
 	 */
-	a = as_area_create((uint8_t *)base + bias, mem_sz,
+	a = as_area_create((uint8_t *) base + bias, mem_sz,
 	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
-	if (a == (void *)(-1)) {
+	if (a == (void *) -1) {
 		DPRINTF("memory mapping failed (0x%x, %d)\n",
-			base+bias, mem_sz);
+		    base + bias, mem_sz);
 		return EE_MEMORY;
 	}
Index: uspace/lib/c/generic/ipc.c
===================================================================
--- uspace/lib/c/generic/ipc.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/generic/ipc.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -48,4 +48,5 @@
 #include <fibril.h>
 #include <macros.h>
+#include "private/libc.h"
 
 /**
@@ -760,22 +761,24 @@
  *
  * @param phoneid Phone that will be used to contact the receiving side.
- * @param dst     Destination address space area base.
  * @param size    Size of the destination address space area.
  * @param arg     User defined argument.
  * @param flags   Storage for received flags. Can be NULL.
+ * @param dst     Destination address space area base. Cannot be NULL.
  *
  * @return Zero on success or a negative error code from errno.h.
  *
  */
-int ipc_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
-    unsigned int *flags)
-{
-	sysarg_t tmp_flags = 0;
-	int res = ipc_call_sync_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
-	    (sysarg_t) size, arg, NULL, &tmp_flags);
+int ipc_share_in_start(int phoneid, size_t size, sysarg_t arg,
+    unsigned int *flags, void **dst)
+{
+	sysarg_t _flags = 0;
+	sysarg_t _dst = (sysarg_t) -1;
+	int res = ipc_call_sync_2_4(phoneid, IPC_M_SHARE_IN, (sysarg_t) size,
+	    arg, NULL, &_flags, NULL, &_dst);
 	
 	if (flags)
-		*flags = (unsigned int) tmp_flags;
-	
+		*flags = (unsigned int) _flags;
+	
+	*dst = (void *) _dst;
 	return res;
 }
@@ -783,5 +786,5 @@
 /** Wrapper for answering the IPC_M_SHARE_IN calls.
  *
- * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
+ * This wrapper only makes it more comfortable to answer IPC_M_SHARE_IN
  * calls so that the user doesn't have to remember the meaning of each
  * IPC argument.
@@ -796,5 +799,6 @@
 int ipc_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags)
 {
-	return ipc_answer_2(callid, EOK, (sysarg_t) src, (sysarg_t) flags);
+	return ipc_answer_3(callid, EOK, (sysarg_t) src, (sysarg_t) flags,
+	    (sysarg_t) __entry);
 }
 
@@ -826,7 +830,7 @@
  *
  */
-int ipc_share_out_finalize(ipc_callid_t callid, void *dst)
-{
-	return ipc_answer_1(callid, EOK, (sysarg_t) dst);
+int ipc_share_out_finalize(ipc_callid_t callid, void **dst)
+{
+	return ipc_answer_2(callid, EOK, (sysarg_t) __entry, (sysarg_t) dst);
 }
 
Index: uspace/lib/c/generic/malloc.c
===================================================================
--- uspace/lib/c/generic/malloc.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/generic/malloc.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -283,13 +283,8 @@
 static bool area_create(size_t size)
 {
-	void *start = as_get_mappable_page(size);
-	if (start == NULL)
-		return false;
-	
-	/* Align the heap area on page boundary */
-	void *astart = (void *) ALIGN_UP((uintptr_t) start, PAGE_SIZE);
+	/* Align the heap area size on page boundary */
 	size_t asize = ALIGN_UP(size, PAGE_SIZE);
-	
-	astart = as_area_create(astart, asize, AS_AREA_WRITE | AS_AREA_READ);
+	void *astart = as_area_create((void *) -1, asize,
+	    AS_AREA_WRITE | AS_AREA_READ);
 	if (astart == (void *) -1)
 		return false;
Index: uspace/lib/c/generic/mman.c
===================================================================
--- uspace/lib/c/generic/mman.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/generic/mman.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -42,5 +42,5 @@
 {
 	if (!start)
-		start = as_get_mappable_page(length);
+		start = (void *) -1;
 	
 //	if (!((flags & MAP_SHARED) ^ (flags & MAP_PRIVATE)))
Index: uspace/lib/c/generic/time.c
===================================================================
--- uspace/lib/c/generic/time.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/generic/time.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -147,12 +147,7 @@
 		}
 		
-		void *addr = as_get_mappable_page(PAGE_SIZE);
-		if (addr == NULL) {
-			errno = ENOMEM;
-			return -1;
-		}
-		
-		rc = physmem_map((void *) faddr, addr, 1,
-		    AS_AREA_READ | AS_AREA_CACHEABLE);
+		void *addr;
+		rc = physmem_map((void *) faddr, 1,
+		    AS_AREA_READ | AS_AREA_CACHEABLE, &addr);
 		if (rc != EOK) {
 			as_area_destroy(addr);
Index: uspace/lib/c/include/as.h
===================================================================
--- uspace/lib/c/include/as.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/include/as.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -59,5 +59,4 @@
 extern int as_area_destroy(void *);
 extern void *set_maxheapsize(size_t);
-extern void *as_get_mappable_page(size_t);
 extern int as_get_physical_mapping(const void *, uintptr_t *);
 
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/include/async.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -346,15 +346,15 @@
  */
 
-#define async_share_in_start_0_0(exch, dst, size) \
-	async_share_in_start(exch, dst, size, 0, NULL)
-#define async_share_in_start_0_1(exch, dst, size, flags) \
-	async_share_in_start(exch, dst, size, 0, flags)
-#define async_share_in_start_1_0(exch, dst, size, arg) \
-	async_share_in_start(exch, dst, size, arg, NULL)
-#define async_share_in_start_1_1(exch, dst, size, arg, flags) \
-	async_share_in_start(exch, dst, size, arg, flags)
-
-extern int async_share_in_start(async_exch_t *, void *, size_t, sysarg_t,
-    unsigned int *);
+#define async_share_in_start_0_0(exch, size, dst) \
+	async_share_in_start(exch, size, 0, NULL, dst)
+#define async_share_in_start_0_1(exch, size, flags, dst) \
+	async_share_in_start(exch, size, 0, flags, dst)
+#define async_share_in_start_1_0(exch, size, arg, dst) \
+	async_share_in_start(exch, size, arg, NULL, dst)
+#define async_share_in_start_1_1(exch, size, arg, flags, dst) \
+	async_share_in_start(exch, size, arg, flags, dst)
+
+extern int async_share_in_start(async_exch_t *, size_t, sysarg_t,
+    unsigned int *, void **);
 extern bool async_share_in_receive(ipc_callid_t *, size_t *);
 extern int async_share_in_finalize(ipc_callid_t, void *, unsigned int);
@@ -362,5 +362,5 @@
 extern int async_share_out_start(async_exch_t *, void *, unsigned int);
 extern bool async_share_out_receive(ipc_callid_t *, size_t *, unsigned int *);
-extern int async_share_out_finalize(ipc_callid_t, void *);
+extern int async_share_out_finalize(ipc_callid_t, void **);
 
 /*
Index: uspace/lib/c/include/ddi.h
===================================================================
--- uspace/lib/c/include/ddi.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/include/ddi.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -42,10 +42,10 @@
 extern int device_assign_devno(void);
 
-extern int physmem_map(void *, void *, size_t, unsigned int);
+extern int physmem_map(void *, size_t, unsigned int, void **);
 
 extern int dmamem_map(void *, size_t, unsigned int, unsigned int, void **);
 extern int dmamem_map_anonymous(size_t, unsigned int, unsigned int, void **,
     void **);
-extern int dmamem_unmap(void *, size_t, unsigned int);
+extern int dmamem_unmap(void *, size_t);
 extern int dmamem_unmap_anonymous(void *);
 
@@ -53,6 +53,6 @@
 extern int pio_enable(void *, size_t, void **);
 
-extern int register_irq(int, int, int, irq_code_t *);
-extern int unregister_irq(int, int);
+extern int irq_register(int, int, int, irq_code_t *);
+extern int irq_unregister(int, int);
 
 #endif
Index: uspace/lib/c/include/device/hw_res.h
===================================================================
--- uspace/lib/c/include/device/hw_res.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/include/device/hw_res.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -40,8 +40,17 @@
 #include <bool.h>
 
+#define DMA_MODE_ON_DEMAND  0
+#define DMA_MODE_WRITE      (1 << 2)
+#define DMA_MODE_READ       (1 << 3)
+#define DMA_MODE_AUTO       (1 << 4)
+#define DMA_MODE_DOWN       (1 << 5)
+#define DMA_MODE_SINGLE     (1 << 6)
+#define DMA_MODE_BLOCK      (1 << 7)
+
 /** HW resource provider interface */
 typedef enum {
 	HW_RES_GET_RESOURCE_LIST = 0,
-	HW_RES_ENABLE_INTERRUPT
+	HW_RES_ENABLE_INTERRUPT,
+	HW_RES_DMA_CHANNEL_SETUP,
 } hw_res_method_t;
 
@@ -50,5 +59,7 @@
 	INTERRUPT,
 	IO_RANGE,
-	MEM_RANGE
+	MEM_RANGE,
+	DMA_CHANNEL_8,
+	DMA_CHANNEL_16,
 } hw_res_type_t;
 
@@ -77,4 +88,9 @@
 			int irq;
 		} interrupt;
+		
+		union {
+			unsigned int dma8;
+			unsigned int dma16;
+		} dma_channel;
 	} res;
 } hw_resource_t;
@@ -98,4 +114,7 @@
 extern bool hw_res_enable_interrupt(async_sess_t *);
 
+extern int hw_res_dma_channel_setup(async_sess_t *, unsigned int, uint32_t,
+    uint16_t, uint8_t);
+
 #endif
 
Index: uspace/lib/c/include/device/hw_res_parsed.h
===================================================================
--- uspace/lib/c/include/device/hw_res_parsed.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/include/device/hw_res_parsed.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -72,4 +72,13 @@
 } irq_list_t;
 
+/** List of ISA DMA channels */
+typedef struct dma_list {
+	/** Channel count */
+	size_t count;
+
+	/** Array of channels */
+	unsigned int *channels;
+} dma_list_t;
+
 /** List of memory areas */
 typedef struct addr_range_list {
@@ -91,4 +100,7 @@
 	/** List of IRQs */
 	irq_list_t irqs;
+	
+	/** List of DMA channels */
+	dma_list_t dma_channels;
 	
 	/** List of memory areas */
@@ -113,4 +125,5 @@
 	free(list->io_ranges.ranges);
 	free(list->mem_ranges.ranges);
+	free(list->dma_channels.channels);
 	
 	bzero(list, sizeof(hw_res_list_parsed_t));
Index: uspace/lib/c/include/ipc/ipc.h
===================================================================
--- uspace/lib/c/include/ipc/ipc.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/c/include/ipc/ipc.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -271,17 +271,17 @@
  */
 
-#define ipc_share_in_start_0_0(phoneid, dst, size) \
-	ipc_share_in_start((phoneid), (dst), (size), 0, NULL)
-#define ipc_share_in_start_0_1(phoneid, dst, size, flags) \
-	ipc_share_in_start((phoneid), (dst), (size), 0, (flags))
-#define ipc_share_in_start_1_0(phoneid, dst, size, arg) \
-	ipc_share_in_start((phoneid), (dst), (size), (arg), NULL)
-#define ipc_share_in_start_1_1(phoneid, dst, size, arg, flags) \
-	ipc_share_in_start((phoneid), (dst), (size), (arg), (flags))
-
-extern int ipc_share_in_start(int, void *, size_t, sysarg_t, unsigned int *);
+#define ipc_share_in_start_0_0(phoneid, size, dst) \
+	ipc_share_in_start((phoneid), (size), 0, NULL, (dst))
+#define ipc_share_in_start_0_1(phoneid, size, flags, dst) \
+	ipc_share_in_start((phoneid), (size), 0, (flags), (dst))
+#define ipc_share_in_start_1_0(phoneid, size, arg, dst) \
+	ipc_share_in_start((phoneid), (size), (arg), NULL, (dst))
+#define ipc_share_in_start_1_1(phoneid, size, arg, flags, dst) \
+	ipc_share_in_start((phoneid), (size), (arg), (flags), (dst))
+
+extern int ipc_share_in_start(int, size_t, sysarg_t, unsigned int *, void **);
 extern int ipc_share_in_finalize(ipc_callid_t, void *, unsigned int);
 extern int ipc_share_out_start(int, void *, unsigned int);
-extern int ipc_share_out_finalize(ipc_callid_t, void *);
+extern int ipc_share_out_finalize(ipc_callid_t, void **);
 extern int ipc_data_read_start(int, void *, size_t);
 extern int ipc_data_read_finalize(ipc_callid_t, const void *, size_t);
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/drv/generic/driver.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -198,5 +198,5 @@
 		pseudocode = &default_pseudocode;
 	
-	int res = register_irq(irq, dev->handle, ctx->id, pseudocode);
+	int res = irq_register(irq, dev->handle, ctx->id, pseudocode);
 	if (res != EOK) {
 		remove_interrupt_context(&interrupt_contexts, ctx);
@@ -211,5 +211,5 @@
 	interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts,
 	    dev, irq);
-	int res = unregister_irq(irq, dev->handle);
+	int res = irq_unregister(irq, dev->handle);
 	
 	if (ctx != NULL) {
Index: uspace/lib/drv/include/ops/hw_res.h
===================================================================
--- uspace/lib/drv/include/ops/hw_res.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/drv/include/ops/hw_res.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -1,4 +1,5 @@
 /*
- * Copyright (c) 2010 Lenka Trochtova 
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
  *
@@ -42,6 +43,7 @@
 
 typedef struct {
-	 hw_resource_list_t *(*get_resource_list)(ddf_fun_t *);
-	 bool (*enable_interrupt)(ddf_fun_t *);
+	hw_resource_list_t *(*get_resource_list)(ddf_fun_t *);
+	bool (*enable_interrupt)(ddf_fun_t *);
+	int (*dma_channel_setup)(ddf_fun_t *, unsigned, uint32_t, uint16_t, uint8_t);
 } hw_res_ops_t;
 
Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
  *
@@ -26,5 +27,4 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup libdrv
  * @addtogroup usb
@@ -46,5 +46,5 @@
 int usbhc_get_handle(async_exch_t *, usb_address_t, devman_handle_t *);
 int usbhc_release_address(async_exch_t *, usb_address_t);
-int usbhc_register_endpoint(async_exch_t *, usb_address_t,  usb_endpoint_t,
+int usbhc_register_endpoint(async_exch_t *, usb_address_t, usb_endpoint_t,
     usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
 int usbhc_unregister_endpoint(async_exch_t *, usb_address_t, usb_endpoint_t,
Index: uspace/lib/fb/imgmap.c
===================================================================
--- uspace/lib/fb/imgmap.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/fb/imgmap.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -420,8 +420,7 @@
 	
 	if ((flags & IMGMAP_FLAG_SHARED) == IMGMAP_FLAG_SHARED) {
-		imgmap = (imgmap_t *) as_get_mappable_page(size);
-		
-		if (as_area_create((void *) imgmap, size, AS_AREA_READ |
-		    AS_AREA_WRITE | AS_AREA_CACHEABLE) != (void *) imgmap)
+		imgmap = (imgmap_t *) as_area_create((void *) -1, size,
+		    AS_AREA_READ | AS_AREA_WRITE);
+		if (imgmap == (void *) -1)
 			return NULL;
 	} else {
Index: uspace/lib/fb/screenbuffer.c
===================================================================
--- uspace/lib/fb/screenbuffer.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/fb/screenbuffer.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -79,8 +79,7 @@
 	
 	if ((flags & SCREENBUFFER_FLAG_SHARED) == SCREENBUFFER_FLAG_SHARED) {
-		scrbuf = (screenbuffer_t *) as_get_mappable_page(size);
-		
-		if (as_area_create((void *) scrbuf, size, AS_AREA_READ |
-		    AS_AREA_WRITE | AS_AREA_CACHEABLE) != (void *) scrbuf)
+		scrbuf = (screenbuffer_t *) as_area_create((void *) -1, size,
+		    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
+		if (scrbuf == (void *) -1)
 			return NULL;
 	} else {
Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/fs/libfs.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -336,17 +336,12 @@
 	
 	/*
-	 * Allocate piece of address space for PLB.
-	 */
-	reg.plb_ro = as_get_mappable_page(PLB_SIZE);
-	if (!reg.plb_ro) {
+	 * Request sharing the Path Lookup Buffer with VFS.
+	 */
+	rc = async_share_in_start_0_0(exch, PLB_SIZE, (void *) &reg.plb_ro);
+	if (reg.plb_ro == (void *) -1) {
 		async_exchange_end(exch);
 		async_wait_for(req, NULL);
 		return ENOMEM;
 	}
-	
-	/*
-	 * Request sharing the Path Lookup Buffer with VFS.
-	 */
-	rc = async_share_in_start_0_0(exch, reg.plb_ro, PLB_SIZE);
 	
 	async_exchange_end(exch);
Index: uspace/lib/net/generic/packet_remote.c
===================================================================
--- uspace/lib/net/generic/packet_remote.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/net/generic/packet_remote.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -66,10 +66,8 @@
     packet_id_t packet_id, size_t size)
 {
-	*packet = (packet_t *) as_get_mappable_page(size);
-	
 	async_exch_t *exch = async_exchange_begin(sess);
 	ipc_call_t answer;
 	aid_t message = async_send_1(exch, NET_PACKET_GET, packet_id, &answer);
-	int rc = async_share_in_start_0_0(exch, *packet, size);
+	int rc = async_share_in_start_0_0(exch, size, (void *) packet);
 	async_exchange_end(exch);
 	
@@ -79,4 +77,7 @@
 	if (rc != EOK)
 		return rc;
+	
+	if (packet == (void *) -1)
+		return ENOMEM;
 	
 	rc = pm_add(*packet);
Index: uspace/lib/nic/src/nic_driver.c
===================================================================
--- uspace/lib/nic/src/nic_driver.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/nic/src/nic_driver.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -1345,5 +1345,5 @@
 int nic_dma_unlock_packet(packet_t *packet, size_t size)
 {
-	return dmamem_unmap(packet, size, 0);
+	return dmamem_unmap(packet, size);
 }
 
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usb/Makefile	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -37,8 +37,8 @@
 	src/class.c \
 	src/ddfiface.c \
+	src/dev.c \
 	src/debug.c \
 	src/dump.c \
 	src/hc.c \
-	src/resolve.c \
 	src/usb.c
 
Index: uspace/lib/usb/include/usb/classes/hub.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hub.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usb/include/usb/classes/hub.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -84,7 +84,8 @@
 
 /**
- *	@brief usb hub descriptor
- *
- *	For more information see Universal Serial Bus Specification Revision 1.1 chapter 11.16.2
+ * @brief usb hub descriptor
+ *
+ * For more information see Universal Serial Bus Specification Revision 1.1
+ * chapter 11.16.2
  */
 typedef struct usb_hub_descriptor_type {
Index: uspace/lib/usb/include/usb/dev.h
===================================================================
--- uspace/lib/usb/include/usb/dev.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
+++ uspace/lib/usb/include/usb/dev.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -0,0 +1,64 @@
+/*
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Common USB types and functions.
+ */
+#ifndef LIBUSB_DEV_H_
+#define LIBUSB_DEV_H_
+
+#include <devman.h>
+#include <usb/usb.h>
+
+int usb_get_info_by_handle(devman_handle_t,
+    devman_handle_t *, usb_address_t *, int *);
+
+static inline int usb_get_hc_by_handle(devman_handle_t dev, devman_handle_t *hc)
+{
+	return usb_get_info_by_handle(dev, hc, NULL, NULL);
+}
+
+static inline int usb_get_address_by_handle(
+    devman_handle_t dev, usb_address_t *address)
+{
+	return usb_get_info_by_handle(dev, NULL, address, NULL);
+}
+
+static inline int usb_get_iface_by_handle(devman_handle_t dev, int *iface)
+{
+	return usb_get_info_by_handle(dev, NULL, NULL, iface);
+}
+
+int usb_resolve_device_handle(const char *, devman_handle_t *, usb_address_t *,
+    devman_handle_t *);
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/hc.h
===================================================================
--- uspace/lib/usb/include/usb/hc.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usb/include/usb/hc.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
  *
@@ -26,23 +27,27 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup libusb
  * @{
  */
 /** @file
- * General communication with host controller driver.
+ * General communication with host controller.
  */
 #ifndef LIBUSB_HC_H_
 #define LIBUSB_HC_H_
 
-#include <sys/types.h>
-#include <ipc/devman.h>
-#include <ipc/loc.h>
+#include <async.h>
+#include <devman.h>
 #include <ddf/driver.h>
 #include <bool.h>
-#include <async.h>
+#include <fibril_synch.h>
 #include <usb/usb.h>
 
-/** Connection to the host controller driver. */
+/** Connection to the host controller driver.
+ *
+ * This is a high level IPC communication wrapper. After the structure has been
+ * initialized using devman handle of an USB host controller, it
+ * will manage all communication to that host controller, including session
+ * creation/destruction and proper IPC protocol.
+ */
 typedef struct {
 	/** Devman handle of the host controller. */
@@ -50,25 +55,64 @@
 	/** Session to the host controller. */
 	async_sess_t *hc_sess;
+	/** Session guard. */
+	fibril_mutex_t guard;
+	/** Use counter. */
+	unsigned ref_count;
 } usb_hc_connection_t;
+
+/** Initialize connection to USB host controller.
+ *
+ * @param connection Connection to be initialized.
+ * @param hc_handle Devman handle of the host controller.
+ * @return Error code.
+ */
+static inline void usb_hc_connection_initialize(usb_hc_connection_t *connection,
+    devman_handle_t hc_handle)
+{
+	assert(connection);
+	connection->hc_handle = hc_handle;
+	connection->hc_sess = NULL;
+	connection->ref_count = 0;
+	fibril_mutex_initialize(&connection->guard);
+}
 
 int usb_hc_connection_initialize_from_device(usb_hc_connection_t *,
     const ddf_dev_t *);
-int usb_hc_connection_initialize(usb_hc_connection_t *, devman_handle_t);
+
+void usb_hc_connection_deinitialize(usb_hc_connection_t *);
 
 int usb_hc_connection_open(usb_hc_connection_t *);
-bool usb_hc_connection_is_opened(const usb_hc_connection_t *);
 int usb_hc_connection_close(usb_hc_connection_t *);
+
+usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_address_t, bool,
+    usb_speed_t);
+int usb_hc_bind_address(usb_hc_connection_t *, usb_address_t, devman_handle_t);
 int usb_hc_get_handle_by_address(usb_hc_connection_t *, usb_address_t,
     devman_handle_t *);
+int usb_hc_release_address(usb_hc_connection_t *, usb_address_t);
 
-usb_address_t usb_get_address_by_handle(devman_handle_t);
+int usb_hc_register_endpoint(usb_hc_connection_t *, usb_address_t,
+    usb_endpoint_t, usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
+int usb_hc_unregister_endpoint(usb_hc_connection_t *, usb_address_t,
+    usb_endpoint_t, usb_direction_t);
 
-int usb_hc_find(devman_handle_t, devman_handle_t *);
+int usb_hc_read(usb_hc_connection_t *, usb_address_t, usb_endpoint_t,
+    uint64_t, void *, size_t, size_t *);
+int usb_hc_write(usb_hc_connection_t *, usb_address_t, usb_endpoint_t,
+    uint64_t, const void *, size_t);
 
-int usb_resolve_device_handle(const char *, devman_handle_t *, usb_address_t *,
-    devman_handle_t *);
-
-int usb_ddf_get_hc_handle_by_sid(service_id_t, devman_handle_t *);
-
+/** Get host controller handle by its class index.
+ *
+ * @param sid Service ID of the HC function.
+ * @param hc_handle Where to store the HC handle
+ *	(can be NULL for existence test only).
+ * @return Error code.
+ */
+static inline int usb_ddf_get_hc_handle_by_sid(
+    service_id_t sid, devman_handle_t *handle)
+{
+	devman_handle_t h;
+	return devman_fun_sid_to_handle(sid, handle ? handle : &h);
+}
 
 #endif
Index: uspace/lib/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usb/include/usb/usb.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -26,5 +26,4 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup libusb
  * @{
Index: uspace/lib/usb/src/ddfiface.c
===================================================================
--- uspace/lib/usb/src/ddfiface.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usb/src/ddfiface.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -44,4 +44,6 @@
 #include <assert.h>
 
+#include <usb/dev.h>
+
 /** DDF interface for USB device, implementation for typical hub. */
 usb_iface_t usb_iface_hub_impl = {
@@ -66,5 +68,5 @@
 {
 	assert(fun);
-	return usb_hc_find(fun->handle, handle);
+	return usb_get_hc_by_handle(fun->handle, handle);
 }
 
@@ -97,23 +99,5 @@
 {
 	assert(fun);
-
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, fun->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-
-	async_exch_t *exch = async_exchange_begin(parent_sess);
-	if (!exch) {
-		async_hangup(parent_sess);
-		return ENOMEM;
-	}
-
-	const int ret = usb_get_my_address(exch, address);
-
-	async_exchange_end(exch);
-	async_hangup(parent_sess);
-
-	return ret;
+	return usb_get_address_by_handle(fun->handle, address);
 }
 
@@ -134,5 +118,5 @@
 	assert(fun);
 	assert(fun->driver_data);
-	usb_hub_attached_device_t *device = fun->driver_data;
+	const usb_hub_attached_device_t *device = fun->driver_data;
 	assert(device->fun == fun);
 	if (address)
Index: uspace/lib/usb/src/dev.c
===================================================================
--- uspace/lib/usb/src/dev.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
+++ uspace/lib/usb/src/dev.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * 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.
+ */
+
+#include <usb/dev.h>
+#include <usb/hc.h>
+#include <errno.h>
+#include <usb_iface.h>
+#include <str.h>
+#include <stdio.h>
+
+#define MAX_DEVICE_PATH 1024
+
+/** Find host controller handle, address and iface number for the device.
+ *
+ * @param[in] device_handle Device devman handle.
+ * @param[out] hc_handle Where to store handle of host controller
+ *	controlling device with @p device_handle handle.
+ * @param[out] address Place to store the device's address
+ * @param[out] iface Place to stoer the assigned USB interface number.
+ * @return Error code.
+ */
+int usb_get_info_by_handle(devman_handle_t device_handle,
+    devman_handle_t *hc_handle, usb_address_t *address, int *iface)
+{
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_ATOMIC, device_handle,
+	        IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+
+	async_exch_t *exch = async_exchange_begin(parent_sess);
+	if (!exch) {
+		async_hangup(parent_sess);
+		return ENOMEM;
+	}
+
+	usb_address_t tmp_address;
+	devman_handle_t tmp_handle;
+	int tmp_iface;
+
+	if (address) {
+		const int ret = usb_get_my_address(exch, &tmp_address);
+		if (ret != EOK) {
+			async_exchange_end(exch);
+			async_hangup(parent_sess);
+			return ret;
+		}
+	}
+
+	if (hc_handle) {
+		const int ret = usb_get_hc_handle(exch, &tmp_handle);
+		if (ret != EOK) {
+			async_exchange_end(exch);
+			async_hangup(parent_sess);
+			return ret;
+		}
+	}
+
+	if (iface) {
+		const int ret = usb_get_my_interface(exch, &tmp_iface);
+		switch (ret) {
+		case ENOTSUP:
+			/* Implementing GET_MY_INTERFACE is voluntary. */
+			tmp_iface = -1;
+		case EOK:
+			break;
+		default:
+			async_exchange_end(exch);
+			async_hangup(parent_sess);
+			return ret;
+		}
+	}
+
+	if (hc_handle)
+		*hc_handle = tmp_handle;
+
+	if (address)
+		*address = tmp_address;
+
+	if (iface)
+		*iface = tmp_iface;
+
+	async_exchange_end(exch);
+	async_hangup(parent_sess);
+
+	return EOK;
+}
+
+static bool try_parse_bus_and_address(const char *path,
+    char **func_start,
+    devman_handle_t *out_hc_handle, usb_address_t *out_device_address)
+{
+	uint64_t sid;
+	size_t address;
+	int rc;
+	char *ptr;
+
+	rc = str_uint64(path, &ptr, 10, false, &sid);
+	if (rc != EOK) {
+		return false;
+	}
+	if ((*ptr == ':') || (*ptr == '.')) {
+		ptr++;
+	} else {
+		return false;
+	}
+	rc = str_size_t(ptr, func_start, 10, false, &address);
+	if (rc != EOK) {
+		return false;
+	}
+	rc = usb_ddf_get_hc_handle_by_sid(sid, out_hc_handle);
+	if (rc != EOK) {
+		return false;
+	}
+	if (out_device_address != NULL) {
+		*out_device_address = (usb_address_t) address;
+	}
+	return true;
+}
+
+static int get_device_handle_by_address(devman_handle_t hc_handle, int addr,
+    devman_handle_t *dev_handle)
+{
+	usb_hc_connection_t conn;
+	usb_hc_connection_initialize(&conn, hc_handle);
+
+	const int rc = usb_hc_get_handle_by_address(&conn, addr, dev_handle);
+
+	return rc;
+}
+
+/** Resolve handle and address of USB device from its path.
+ *
+ * This is a wrapper working on best effort principle.
+ * If the resolving fails, if will not give much details about what
+ * is wrong.
+ * Typically, error from this function would be reported to the user
+ * as "bad device specification" or "device does not exist".
+ *
+ * The path can be specified in following format:
+ *  - devman path (e.g. /hw/pci0/.../usb01_a5
+ *  - bus number and device address (e.g. 5.1)
+ *  - bus number, device address and device function (e.g. 2.1/HID0/keyboard)
+ *
+ * @param[in] dev_path Path to the device.
+ * @param[out] out_hc_handle Where to store handle of a parent host controller.
+ * @param[out] out_dev_addr Where to store device (USB) address.
+ * @param[out] out_dev_handle Where to store device handle.
+ * @return Error code.
+ */
+int usb_resolve_device_handle(const char *dev_path, devman_handle_t *out_hc_handle,
+    usb_address_t *out_dev_addr, devman_handle_t *out_dev_handle)
+{
+	if (dev_path == NULL) {
+		return EBADMEM;
+	}
+
+	bool found_hc = false;
+	bool found_addr = false;
+	devman_handle_t hc_handle, dev_handle;
+	usb_address_t dev_addr = -1;
+	int rc;
+	bool is_bus_addr;
+	char *func_start = NULL;
+	char *path = NULL;
+
+	/* First try the BUS.ADDR format. */
+	is_bus_addr = try_parse_bus_and_address(dev_path, &func_start,
+	    &hc_handle, &dev_addr);
+	if (is_bus_addr) {
+		found_hc = true;
+		found_addr = true;
+		/*
+		 * Now get the handle of the device. We will need that
+		 * in both cases. If there is only BUS.ADDR, it will
+		 * be the handle to be returned to the caller, otherwise
+		 * we will need it to resolve the path to which the
+		 * suffix would be appended.
+		 */
+		/* If there is nothing behind the BUS.ADDR, we will
+		 * get the device handle from the host controller.
+		 * Otherwise, we will
+		 */
+		rc = get_device_handle_by_address(hc_handle, dev_addr,
+		    &dev_handle);
+		if (rc != EOK) {
+			return rc;
+		}
+		if (str_length(func_start) > 0) {
+			char tmp_path[MAX_DEVICE_PATH];
+			rc = devman_fun_get_path(dev_handle,
+			    tmp_path, MAX_DEVICE_PATH);
+			if (rc != EOK) {
+				return rc;
+			}
+			rc = asprintf(&path, "%s%s", tmp_path, func_start);
+			if (rc < 0) {
+				return ENOMEM;
+			}
+		} else {
+			/* Everything is resolved. Get out of here. */
+			goto copy_out;
+		}
+	} else {
+		path = str_dup(dev_path);
+		if (path == NULL) {
+			return ENOMEM;
+		}
+	}
+
+	/* First try to get the device handle. */
+	rc = devman_fun_get_handle(path, &dev_handle, 0);
+	if (rc != EOK) {
+		free(path);
+		/* Invalid path altogether. */
+		return rc;
+	}
+
+	/* Remove suffixes and hope that we will encounter device node. */
+	while (str_length(path) > 0) {
+		/* Get device handle first. */
+		devman_handle_t tmp_handle;
+		rc = devman_fun_get_handle(path, &tmp_handle, 0);
+		if (rc != EOK) {
+			free(path);
+			return rc;
+		}
+
+		/* Try to find its host controller. */
+		if (!found_hc) {
+			rc = usb_get_hc_by_handle(tmp_handle, &hc_handle);
+			if (rc == EOK) {
+				found_hc = true;
+			}
+		}
+
+		/* Try to get its address. */
+		if (!found_addr) {
+			rc = usb_get_address_by_handle(tmp_handle, &dev_addr);
+			if (rc == 0) {
+				found_addr = true;
+			}
+		}
+
+		/* Speed-up. */
+		if (found_hc && found_addr) {
+			break;
+		}
+
+		/* Remove the last suffix. */
+		char *slash_pos = str_rchr(path, '/');
+		if (slash_pos != NULL) {
+			*slash_pos = 0;
+		}
+	}
+
+	free(path);
+
+	if (!found_addr || !found_hc) {
+		return ENOENT;
+	}
+
+copy_out:
+	if (out_dev_addr != NULL) {
+		*out_dev_addr = dev_addr;
+	}
+	if (out_hc_handle != NULL) {
+		*out_hc_handle = hc_handle;
+	}
+	if (out_dev_handle != NULL) {
+		*out_dev_handle = dev_handle;
+	}
+
+	return EOK;
+}
Index: uspace/lib/usb/src/hc.c
===================================================================
--- uspace/lib/usb/src/hc.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usb/src/hc.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
  *
@@ -26,5 +27,4 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup libusb
  * @{
@@ -33,13 +33,72 @@
  * General communication with host controller driver (implementation).
  */
-#include <devman.h>
-#include <async.h>
-#include <dev_iface.h>
-#include <usb_iface.h>
+#include <usb/debug.h>
+
+#include <assert.h>
+#include <errno.h>
 #include <usbhc_iface.h>
+#include <usb/dev.h>
 #include <usb/hc.h>
-#include <usb/debug.h>
-#include <errno.h>
-#include <assert.h>
+
+static int usb_hc_connection_add_ref(usb_hc_connection_t *connection)
+{
+	assert(connection);
+	fibril_mutex_lock(&connection->guard);
+	if (connection->ref_count == 0) {
+		assert(connection->hc_sess == NULL);
+		/* Parallel exchange for us */
+		connection->hc_sess = devman_device_connect(EXCHANGE_PARALLEL,
+		        connection->hc_handle, 0);
+		if (!connection->hc_sess) {
+			fibril_mutex_unlock(&connection->guard);
+			return ENOMEM;
+		}
+	}
+	++connection->ref_count;
+	fibril_mutex_unlock(&connection->guard);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int usb_hc_connection_del_ref(usb_hc_connection_t *connection)
+{
+	assert(connection);
+	fibril_mutex_lock(&connection->guard);
+	if (connection->ref_count == 0) {
+		/* Closing already closed connection... */
+		assert(connection->hc_sess = NULL);
+		fibril_mutex_unlock(&connection->guard);
+		return EOK;
+	}
+	--connection->ref_count;
+	int ret = EOK;
+	if (connection->ref_count == 0) {
+		assert(connection->hc_sess);
+		ret = async_hangup(connection->hc_sess);
+		connection->hc_sess = NULL;
+	}
+	fibril_mutex_unlock(&connection->guard);
+	return ret;
+}
+
+#define EXCH_INIT(connection, exch) \
+do { \
+	exch = NULL; \
+	if (!connection) \
+		return EBADMEM; \
+	const int ret = usb_hc_connection_add_ref(connection); \
+	if (ret != EOK) \
+		return ret; \
+	exch = async_exchange_begin(connection->hc_sess); \
+	if (exch == NULL) { \
+		usb_hc_connection_del_ref(connection); \
+		return ENOMEM; \
+	} \
+} while (0)
+
+#define EXCH_FINI(connection, exch) \
+if (exch) { \
+	async_exchange_end(exch); \
+	usb_hc_connection_del_ref(connection); \
+} else (void)0
 
 /** Initialize connection to USB host controller.
@@ -59,31 +118,27 @@
 
 	devman_handle_t hc_handle;
-	int rc = usb_hc_find(device->handle, &hc_handle);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	rc = usb_hc_connection_initialize(connection, hc_handle);
+	const int rc = usb_get_hc_by_handle(device->handle, &hc_handle);
+	if (rc == EOK) {
+		usb_hc_connection_initialize(connection, hc_handle);
+	}
 
 	return rc;
 }
-
-/** Manually initialize connection to USB host controller.
- *
- * @param connection Connection to be initialized.
- * @param hc_handle Devman handle of the host controller.
- * @return Error code.
- */
-int usb_hc_connection_initialize(usb_hc_connection_t *connection,
-    devman_handle_t hc_handle)
-{
-	assert(connection);
-
-	connection->hc_handle = hc_handle;
-	connection->hc_sess = NULL;
-
-	return EOK;
-}
-
+/*----------------------------------------------------------------------------*/
+void usb_hc_connection_deinitialize(usb_hc_connection_t *connection)
+{
+	assert(connection);
+	fibril_mutex_lock(&connection->guard);
+	if (connection->ref_count != 0) {
+		usb_log_warning("%u stale reference(s) to HC connection.\n",
+		    connection->ref_count);
+		assert(connection->hc_sess);
+		async_hangup(connection->hc_sess);
+		connection->hc_sess = NULL;
+		connection->ref_count = 0;
+	}
+	fibril_mutex_unlock(&connection->guard);
+}
+/*----------------------------------------------------------------------------*/
 /** Open connection to host controller.
  *
@@ -93,52 +148,51 @@
 int usb_hc_connection_open(usb_hc_connection_t *connection)
 {
-	assert(connection);
-	
-	if (usb_hc_connection_is_opened(connection))
-		return EBUSY;
-	
-	async_sess_t *sess = devman_device_connect(EXCHANGE_ATOMIC,
-	    connection->hc_handle, 0);
-	if (!sess)
-		return ENOMEM;
-	
-	connection->hc_sess = sess;
-	return EOK;
-}
-
-/** Tells whether connection to host controller is opened.
+	return usb_hc_connection_add_ref(connection);
+}
+/*----------------------------------------------------------------------------*/
+/** Close connection to the host controller.
  *
  * @param connection Connection to the host controller.
- * @return Whether connection is opened.
- */
-bool usb_hc_connection_is_opened(const usb_hc_connection_t *connection)
-{
-	assert(connection);
-	return (connection->hc_sess != NULL);
-}
-
-/** Close connection to the host controller.
- *
- * @param connection Connection to the host controller.
  * @return Error code.
  */
 int usb_hc_connection_close(usb_hc_connection_t *connection)
 {
-	assert(connection);
-
-	if (!usb_hc_connection_is_opened(connection)) {
-		return ENOENT;
-	}
-
-	int rc = async_hangup(connection->hc_sess);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	connection->hc_sess = NULL;
-
-	return EOK;
-}
-
+	return usb_hc_connection_del_ref(connection);
+}
+/*----------------------------------------------------------------------------*/
+/** Ask host controller for free address assignment.
+ *
+ * @param connection Opened connection to host controller.
+ * @param preferred Preferred SUB address.
+ * @param strict Fail if the preferred address is not avialable.
+ * @param speed Speed of the new device (device that will be assigned
+ *    the returned address).
+ * @return Assigned USB address or negative error code.
+ */
+usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
+    usb_address_t preferred, bool strict, usb_speed_t speed)
+{
+	async_exch_t *exch;
+	EXCH_INIT(connection, exch);
+
+	usb_address_t address = preferred;
+	const int ret = usbhc_request_address(exch, &address, strict, speed);
+
+	EXCH_FINI(connection, exch);
+	return ret == EOK ? address : ret;
+}
+/*----------------------------------------------------------------------------*/
+int usb_hc_bind_address(usb_hc_connection_t * connection,
+    usb_address_t address, devman_handle_t handle)
+{
+	async_exch_t *exch;
+	EXCH_INIT(connection, exch);
+
+	const int ret = usbhc_bind_address(exch, address, handle);
+
+	EXCH_FINI(connection, exch);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
 /** Get handle of USB device with given address.
  *
@@ -151,90 +205,75 @@
     usb_address_t address, devman_handle_t *handle)
 {
-	if (!usb_hc_connection_is_opened(connection))
-		return ENOENT;
-
-	async_exch_t *exch = async_exchange_begin(connection->hc_sess);
-	if (!exch)
-		return ENOMEM;
+	async_exch_t *exch;
+	EXCH_INIT(connection, exch);
+
 	const int ret = usbhc_get_handle(exch, address, handle);
-	async_exchange_end(exch);
-	return ret;
-}
-
-/** Tell USB address assigned to device with given handle.
- *
- * @param dev_handle Devman handle of the USB device in question.
- * @return USB address or negative error code.
- */
-usb_address_t usb_get_address_by_handle(devman_handle_t dev_handle)
-{
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_ATOMIC, dev_handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-
-	async_exch_t *exch = async_exchange_begin(parent_sess);
-	if (!exch) {
-		async_hangup(parent_sess);
-		return ENOMEM;
-	}
-	usb_address_t address;
-	const int ret = usb_get_my_address(exch, &address);
-
-	async_exchange_end(exch);
-	async_hangup(parent_sess);
-
-	if (ret != EOK)
-		return ret;
-
-	return address;
-}
-
-
-/** Get host controller handle by its class index.
- *
- * @param sid Service ID of the HC function.
- * @param hc_handle Where to store the HC handle
- *	(can be NULL for existence test only).
- * @return Error code.
- */
-int usb_ddf_get_hc_handle_by_sid(service_id_t sid, devman_handle_t *hc_handle)
-{
-	devman_handle_t handle;
-	int rc;
-	
-	rc = devman_fun_sid_to_handle(sid, &handle);
-	if (hc_handle != NULL)
-		*hc_handle = handle;
-	
-	return rc;
-}
-
-/** Find host controller handle that is ancestor of given device.
- *
- * @param[in] device_handle Device devman handle.
- * @param[out] hc_handle Where to store handle of host controller
- *	controlling device with @p device_handle handle.
- * @return Error code.
- */
-int usb_hc_find(devman_handle_t device_handle, devman_handle_t *hc_handle)
-{
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_ATOMIC, device_handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-
-	async_exch_t *exch = async_exchange_begin(parent_sess);
-	if (!exch) {
-		async_hangup(parent_sess);
-		return ENOMEM;
-	}
-	const int ret = usb_get_hc_handle(exch, hc_handle);
-
-	async_exchange_end(exch);
-	async_hangup(parent_sess);
-
+
+	EXCH_FINI(connection, exch);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+int usb_hc_release_address(usb_hc_connection_t *connection,
+    usb_address_t address)
+{
+	async_exch_t *exch;
+	EXCH_INIT(connection, exch);
+
+	const int ret = usbhc_release_address(exch, address);
+
+	EXCH_FINI(connection, exch);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+int usb_hc_register_endpoint(usb_hc_connection_t *connection,
+    usb_address_t address, usb_endpoint_t endpoint, usb_transfer_type_t type,
+    usb_direction_t direction, size_t packet_size, unsigned interval)
+{
+	async_exch_t *exch;
+	EXCH_INIT(connection, exch);
+
+	const int ret = usbhc_register_endpoint(exch, address, endpoint,
+	    type, direction, packet_size, interval);
+
+	EXCH_FINI(connection, exch);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+int usb_hc_unregister_endpoint(usb_hc_connection_t *connection,
+    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	async_exch_t *exch;
+	EXCH_INIT(connection, exch);
+
+	const int ret =
+	    usbhc_unregister_endpoint(exch, address, endpoint, direction);
+
+	EXCH_FINI(connection, exch);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+int usb_hc_read(usb_hc_connection_t *connection, usb_address_t address,
+    usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size,
+    size_t *real_size)
+{
+	async_exch_t *exch;
+	EXCH_INIT(connection, exch);
+
+	const int ret =
+	    usbhc_read(exch, address, endpoint, setup, data, size, real_size);
+
+	EXCH_FINI(connection, exch);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+int usb_hc_write(usb_hc_connection_t *connection, usb_address_t address,
+    usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size)
+{
+	async_exch_t *exch;
+	EXCH_INIT(connection, exch);
+
+	const int ret = usbhc_write(exch, address, endpoint, setup, data, size);
+
+	EXCH_FINI(connection, exch);
 	return ret;
 }
Index: pace/lib/usb/src/resolve.c
===================================================================
--- uspace/lib/usb/src/resolve.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ 	(revision )
@@ -1,244 +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 libusb
- * @{
- */
-/** @file
- *
- */
-#include <inttypes.h>
-#include <usb/hc.h>
-#include <devman.h>
-#include <errno.h>
-#include <str.h>
-#include <stdio.h>
-
-#define MAX_DEVICE_PATH 1024
-
-static bool try_parse_bus_and_address(const char *path,
-    char **func_start,
-    devman_handle_t *out_hc_handle, usb_address_t *out_device_address)
-{
-	uint64_t sid;
-	size_t address;
-	int rc;
-	char *ptr;
-
-	rc = str_uint64(path, &ptr, 10, false, &sid);
-	if (rc != EOK) {
-		return false;
-	}
-	if ((*ptr == ':') || (*ptr == '.')) {
-		ptr++;
-	} else {
-		return false;
-	}
-	rc = str_size_t(ptr, func_start, 10, false, &address);
-	if (rc != EOK) {
-		return false;
-	}
-	rc = usb_ddf_get_hc_handle_by_sid(sid, out_hc_handle);
-	if (rc != EOK) {
-		return false;
-	}
-	if (out_device_address != NULL) {
-		*out_device_address = (usb_address_t) address;
-	}
-	return true;
-}
-
-static int get_device_handle_by_address(devman_handle_t hc_handle, int addr,
-    devman_handle_t *dev_handle)
-{
-	int rc;
-	usb_hc_connection_t conn;
-
-	usb_hc_connection_initialize(&conn, hc_handle);
-	rc = usb_hc_connection_open(&conn);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	rc = usb_hc_get_handle_by_address(&conn, addr, dev_handle);
-
-	usb_hc_connection_close(&conn);
-
-	return rc;
-}
-
-/** Resolve handle and address of USB device from its path.
- *
- * This is a wrapper working on best effort principle.
- * If the resolving fails, if will not give much details about what
- * is wrong.
- * Typically, error from this function would be reported to the user
- * as "bad device specification" or "device does not exist".
- *
- * The path can be specified in following format:
- *  - devman path (e.g. /hw/pci0/.../usb01_a5
- *  - bus number and device address (e.g. 5.1)
- *  - bus number, device address and device function (e.g. 2.1/HID0/keyboard)
- *
- * @param[in] dev_path Path to the device.
- * @param[out] out_hc_handle Where to store handle of a parent host controller.
- * @param[out] out_dev_addr Where to store device (USB) address.
- * @param[out] out_dev_handle Where to store device handle.
- * @return Error code.
- */
-int usb_resolve_device_handle(const char *dev_path, devman_handle_t *out_hc_handle,
-    usb_address_t *out_dev_addr, devman_handle_t *out_dev_handle)
-{
-	if (dev_path == NULL) {
-		return EBADMEM;
-	}
-
-	bool found_hc = false;
-	bool found_addr = false;
-	devman_handle_t hc_handle, dev_handle;
-	usb_address_t dev_addr = -1;
-	int rc;
-	bool is_bus_addr;
-	char *func_start = NULL;
-	char *path = NULL;
-
-	/* First try the BUS.ADDR format. */
-	is_bus_addr = try_parse_bus_and_address(dev_path, &func_start,
-	    &hc_handle, &dev_addr);
-	if (is_bus_addr) {
-		found_hc = true;
-		found_addr = true;
-		/*
-		 * Now get the handle of the device. We will need that
-		 * in both cases. If there is only BUS.ADDR, it will
-		 * be the handle to be returned to the caller, otherwise
-		 * we will need it to resolve the path to which the
-		 * suffix would be appended.
-		 */
-		/* If there is nothing behind the BUS.ADDR, we will
-		 * get the device handle from the host controller.
-		 * Otherwise, we will
-		 */
-		rc = get_device_handle_by_address(hc_handle, dev_addr,
-		    &dev_handle);
-		if (rc != EOK) {
-			return rc;
-		}
-		if (str_length(func_start) > 0) {
-			char tmp_path[MAX_DEVICE_PATH ];
-			rc = devman_fun_get_path(dev_handle,
-			    tmp_path, MAX_DEVICE_PATH);
-			if (rc != EOK) {
-				return rc;
-			}
-			rc = asprintf(&path, "%s%s", tmp_path, func_start);
-			if (rc < 0) {
-				return ENOMEM;
-			}
-		} else {
-			/* Everything is resolved. Get out of here. */
-			goto copy_out;
-		}
-	} else {
-		path = str_dup(dev_path);
-		if (path == NULL) {
-			return ENOMEM;
-		}
-	}
-
-	/* First try to get the device handle. */
-	rc = devman_fun_get_handle(path, &dev_handle, 0);
-	if (rc != EOK) {
-		free(path);
-		/* Invalid path altogether. */
-		return rc;
-	}
-
-	/* Remove suffixes and hope that we will encounter device node. */
-	while (str_length(path) > 0) {
-		/* Get device handle first. */
-		devman_handle_t tmp_handle;
-		rc = devman_fun_get_handle(path, &tmp_handle, 0);
-		if (rc != EOK) {
-			free(path);
-			return rc;
-		}
-
-		/* Try to find its host controller. */
-		if (!found_hc) {
-			rc = usb_hc_find(tmp_handle, &hc_handle);
-			if (rc == EOK) {
-				found_hc = true;
-			}
-		}
-
-		/* Try to get its address. */
-		if (!found_addr) {
-			dev_addr = usb_get_address_by_handle(tmp_handle);
-			if (dev_addr >= 0) {
-				found_addr = true;
-			}
-		}
-
-		/* Speed-up. */
-		if (found_hc && found_addr) {
-			break;
-		}
-
-		/* Remove the last suffix. */
-		char *slash_pos = str_rchr(path, '/');
-		if (slash_pos != NULL) {
-			*slash_pos = 0;
-		}
-	}
-
-	free(path);
-
-	if (!found_addr || !found_hc) {
-		return ENOENT;
-	}
-
-copy_out:
-	if (out_dev_addr != NULL) {
-		*out_dev_addr = dev_addr;
-	}
-	if (out_hc_handle != NULL) {
-		*out_hc_handle = hc_handle;
-	}
-	if (out_dev_handle != NULL) {
-		*out_dev_handle = dev_handle;
-	}
-
-	return EOK;
-}
-
-
-/**
- * @}
- */
-
Index: uspace/lib/usb/src/usb.c
===================================================================
--- uspace/lib/usb/src/usb.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usb/src/usb.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -39,27 +39,27 @@
 
 static const char *str_speed[] = {
-	"low",
-	"full",
-	"high"
+	[USB_SPEED_LOW] = "low",
+	[USB_SPEED_FULL] = "full",
+	[USB_SPEED_HIGH] = "high",
 };
 
 static const char *str_transfer_type[] = {
-	"control",
-	"isochronous",
-	"bulk",
-	"interrupt"
+	[USB_TRANSFER_CONTROL] = "control",
+	[USB_TRANSFER_ISOCHRONOUS] = "isochronous",
+	[USB_TRANSFER_BULK] = "bulk",
+	[USB_TRANSFER_INTERRUPT] = "interrupt",
 };
 
 static const char *str_transfer_type_short[] = {
-	"ctrl",
-	"iso",
-	"bulk",
-	"intr"
+	[USB_TRANSFER_CONTROL] = "ctrl",
+	[USB_TRANSFER_ISOCHRONOUS] = "iso",
+	[USB_TRANSFER_BULK] = "bulk",
+	[USB_TRANSFER_INTERRUPT] = "intr",
 };
 
 static const char *str_direction[] = {
-	"in",
-	"out",
-	"both"
+	[USB_DIRECTION_IN] = "in",
+	[USB_DIRECTION_OUT] = "out",
+	[USB_DIRECTION_BOTH] = "both",
 };
 
Index: uspace/lib/usbdev/Makefile
===================================================================
--- uspace/lib/usbdev/Makefile	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbdev/Makefile	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -40,9 +40,6 @@
 	src/dp.c \
 	src/hub.c \
-	src/pipepriv.c \
-	src/pipepriv.h \
 	src/pipes.c \
 	src/pipesinit.c \
-	src/pipesio.c \
 	src/recognise.c \
 	src/request.c
Index: uspace/lib/usbdev/include/usb/dev/driver.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/driver.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbdev/include/usb/dev/driver.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -36,4 +36,6 @@
 #define LIBUSBDEV_DRIVER_H_
 
+#include <usb/hc.h>
+#include <usb/dev/usb_device_connection.h>
 #include <usb/dev/pipes.h>
 
@@ -72,4 +74,6 @@
 /** USB device structure. */
 typedef struct {
+	/** Connection to USB hc, used by wire and arbitrary requests. */
+	usb_hc_connection_t hc_conn;
 	/** Connection backing the pipes.
 	 * Typically, you will not need to use this attribute at all.
@@ -169,8 +173,8 @@
 void usb_device_release_descriptors(usb_device_descriptors_t *);
 
-int usb_device_create_pipes(const ddf_dev_t *, usb_device_connection_t *,
+int usb_device_create_pipes(usb_device_connection_t *,
     const usb_endpoint_description_t **, const uint8_t *, size_t, int, int,
     usb_endpoint_mapping_t **, size_t *);
-int usb_device_destroy_pipes(const ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
+void usb_device_destroy_pipes(usb_endpoint_mapping_t *, size_t);
 
 void * usb_device_data_alloc(usb_device_t *, size_t);
Index: uspace/lib/usbdev/include/usb/dev/hub.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/hub.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbdev/include/usb/dev/hub.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -40,4 +40,5 @@
 #include <ddf/driver.h>
 #include <sys/types.h>
+#include <errno.h>
 #include <usb/hc.h>
 
@@ -59,9 +60,15 @@
 } usb_hub_attached_device_t;
 
-usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_address_t,
-    bool, usb_speed_t);
-int usb_hc_register_device(usb_hc_connection_t *,
+int usb_hub_register_device(usb_hc_connection_t *,
     const usb_hub_attached_device_t *);
-int usb_hc_unregister_device(usb_hc_connection_t *, usb_address_t);
+
+static inline int usb_hub_unregister_device(usb_hc_connection_t *conn,
+    const usb_hub_attached_device_t *attached_device)
+{
+	assert(conn);
+	if (attached_device == NULL)
+		return EBADMEM;
+	return usb_hc_release_address(conn, attached_device->address);
+}
 
 #endif
Index: uspace/lib/usbdev/include/usb/dev/pipes.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/pipes.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbdev/include/usb/dev/pipes.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -26,5 +26,4 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup libusbdev
  * @{
@@ -37,38 +36,18 @@
 
 #include <sys/types.h>
-#include <usb/usb.h>
-#include <usb/hc.h>
-#include <usb/descriptor.h>
 #include <ipc/devman.h>
 #include <ddf/driver.h>
 #include <fibril_synch.h>
-#include <async.h>
+#include <usb/usb.h>
+#include <usb/descriptor.h>
+#include <usb/dev/usb_device_connection.h>
 
-/** Abstraction of a physical connection to the device.
- * This type is an abstraction of the USB wire that connects the host and
- * the function (device).
+#define CTRL_PIPE_MIN_PACKET_SIZE 8
+/** Abstraction of a logical connection to USB device endpoint.
+ * It encapsulates endpoint attributes (transfer type etc.).
+ * This endpoint must be bound with existing usb_device_connection_t
+ * (i.e. the wire to send data over).
  */
 typedef struct {
-	/** Handle of the host controller device is connected to. */
-	devman_handle_t hc_handle;
-	/** Address of the device. */
-	usb_address_t address;
-} usb_device_connection_t;
-
-/** Abstraction of a logical connection to USB device endpoint.
- * It encapsulates endpoint attributes (transfer type etc.) as well
- * as information about currently running sessions.
- * This endpoint must be bound with existing usb_device_connection_t
- * (i.e. the wire to send data over).
- *
- * Locking order: if you want to lock both mutexes
- * (@c guard and @c hc_sess_mutex), lock @c guard first.
- * It is not necessary to lock @c guard if you want to lock @c hc_sess_mutex
- * only.
- */
-typedef struct {
-	/** Guard of the whole pipe. */
-	fibril_mutex_t guard;
-
 	/** The connection used for sending the data. */
 	usb_device_connection_t *wire;
@@ -86,33 +65,4 @@
 	size_t max_packet_size;
 
-	/** Session to the host controller.
-	 * NULL when no session is active.
-	 * It is an error to access this member without @c hc_sess_mutex
-	 * being locked.
-	 * If call over the phone is to be made, it must be preceeded by
-	 * call to pipe_add_ref() [internal libusb function].
-	 */
-	async_sess_t *hc_sess;
-
-	/** Guard for serialization of requests over the session. */
-	fibril_mutex_t hc_sess_mutex;
-
-	/** Number of active transfers over the pipe. */
-	int refcount;
-	/** Number of failed attempts to open the HC phone.
-	 * When user requests usb_pipe_start_long_transfer() and the operation
-	 * fails, there is no way to report this to the user.
-	 * That the soft reference counter is increased to record the attempt.
-	 * When the user then request e.g. usb_pipe_read(), it will try to
-	 * add reference as well.
-	 * If that fails, it is reported to the user. If it is okay, the
-	 * real reference counter is incremented.
-	 * The problem might arise when ending the long transfer (since
-	 * the number of references would be only 1, but logically it shall be
-	 * two).
-	 * Decrementing the soft counter first shall solve this.
-	 */
-	int refcount_soft;
-
 	/** Whether to automatically reset halt on the endpoint.
 	 * Valid only for control endpoint zero.
@@ -120,5 +70,4 @@
 	bool auto_reset_halt;
 } usb_pipe_t;
-
 
 /** Description of endpoint characteristics. */
@@ -156,25 +105,18 @@
 } usb_endpoint_mapping_t;
 
-int usb_device_connection_initialize_on_default_address(
-    usb_device_connection_t *, usb_hc_connection_t *);
-int usb_device_connection_initialize_from_device(usb_device_connection_t *,
-    const ddf_dev_t *);
-int usb_device_connection_initialize(usb_device_connection_t *,
-    devman_handle_t, usb_address_t);
-
-int usb_device_get_assigned_interface(const ddf_dev_t *);
-
 int usb_pipe_initialize(usb_pipe_t *, usb_device_connection_t *,
     usb_endpoint_t, usb_transfer_type_t, size_t, usb_direction_t);
 int usb_pipe_initialize_default_control(usb_pipe_t *,
     usb_device_connection_t *);
+
 int usb_pipe_probe_default_control(usb_pipe_t *);
 int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
     size_t, const uint8_t *, size_t, usb_device_connection_t *);
-int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *);
-int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *);
 
-void usb_pipe_start_long_transfer(usb_pipe_t *);
-void usb_pipe_end_long_transfer(usb_pipe_t *);
+int usb_pipe_register(usb_pipe_t *, unsigned);
+int usb_pipe_unregister(usb_pipe_t *);
+
+int usb_pipe_start_long_transfer(usb_pipe_t *);
+int usb_pipe_end_long_transfer(usb_pipe_t *);
 
 int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *);
Index: uspace/lib/usbdev/include/usb/dev/poll.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/poll.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbdev/include/usb/dev/poll.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -39,4 +39,5 @@
 #include <time.h>
 
+/** Parameters and callbacks for automated polling. */
 typedef struct {
 	/** Level of debugging messages from auto polling.
@@ -82,8 +83,10 @@
 	 */
 	bool (*on_error)(usb_device_t *dev, int err_code, void *arg);
+	/** Argument to pass to callbacks. */
+	void *arg;
 } usb_device_auto_polling_t;
 
 int usb_device_auto_polling(usb_device_t *, size_t,
-    const usb_device_auto_polling_t *, size_t, void *);
+    const usb_device_auto_polling_t *, size_t);
 
 typedef bool (*usb_polling_callback_t)(usb_device_t *,
Index: uspace/lib/usbdev/include/usb/dev/request.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/request.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbdev/include/usb/dev/request.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -83,4 +83,10 @@
 	uint8_t request_type;
 #define SETUP_REQUEST_TYPE_DEVICE_TO_HOST (1 << 7)
+#define SETUP_REQUEST_TYPE_GET_TYPE(rt) ((rt >> 5) & 0x3)
+#define SETUP_REQUEST_TYPE_GET_RECIPIENT(rec) (rec & 0x1f)
+#define SETUP_REQUEST_TO_HOST(type, recipient) \
+    (uint8_t)((1 << 7) | ((type & 0x3) << 5) | (recipient & 0x1f))
+#define SETUP_REQUEST_TO_DEVICE(type, recipient) \
+    (uint8_t)(((type & 0x3) << 5) | (recipient & 0x1f))
 
 	/** Request identification. */
Index: uspace/lib/usbdev/include/usb/dev/usb_device_connection.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/usb_device_connection.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
+++ uspace/lib/usbdev/include/usb/dev/usb_device_connection.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -0,0 +1,172 @@
+/*
+ * 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 libusbdev
+ * @{
+ */
+/** @file
+ * Common USB types and functions.
+ */
+#ifndef LIBUSBDEV_DEVICE_CONNECTION_H_
+#define LIBUSBDEV_DEVICE_CONNECTION_H_
+
+#include <errno.h>
+#include <devman.h>
+#include <usb/usb.h>
+#include <usb/hc.h>
+
+
+/** Abstraction of a physical connection to the device.
+ * This type is an abstraction of the USB wire that connects the host and
+ * the function (device).
+ */
+typedef struct {
+	/** Connection to the host controller device is connected to. */
+	usb_hc_connection_t *hc_connection;
+	/** Address of the device. */
+	usb_address_t address;
+} usb_device_connection_t;
+
+/** Initialize device connection. Set address and hc connection.
+ * @param instance Structure to initialize.
+ * @param hc_connection. Host controller connection to use.
+ * @param address USB address.
+ * @return Error code.
+ */
+static inline int usb_device_connection_initialize(
+    usb_device_connection_t *instance, usb_hc_connection_t *hc_connection,
+    usb_address_t address)
+{
+	assert(instance);
+	if (hc_connection == NULL)
+		return EBADMEM;
+	if ((address < 0) || (address >= USB11_ADDRESS_MAX))
+		return EINVAL;
+
+	instance->hc_connection = hc_connection;
+	instance->address = address;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Register endpoint on the device.
+ * @param instance device connection structure to use.
+ * @param ep USB endpoint number.
+ * @param type Communication type of the endpoint.
+ * @param direction Communication direction.
+ * @param packet_size Maximum packet size for the endpoint.
+ * @param interval Preferrred interval between communication.
+ * @return Error code.
+ */
+static inline int usb_device_register_endpoint(
+    usb_device_connection_t *instance, usb_endpoint_t ep,
+    usb_transfer_type_t type, usb_direction_t direction,
+    size_t packet_size, unsigned interval)
+{
+	assert(instance);
+	return usb_hc_register_endpoint(instance->hc_connection,
+	    instance->address, ep, type, direction, packet_size, interval);
+}
+/*----------------------------------------------------------------------------*/
+/** Unregister endpoint on the device.
+ * @param instance device connection structure
+ * @param ep Endpoint number.
+ * @param dir Communication direction.
+ * @return Error code.
+ */
+static inline int usb_device_unregister_endpoint(
+    usb_device_connection_t *instance, usb_endpoint_t ep, usb_direction_t dir)
+{
+	assert(instance);
+	return usb_hc_unregister_endpoint(instance->hc_connection,
+	    instance->address, ep, dir);
+}
+/*----------------------------------------------------------------------------*/
+/** Get data from the device.
+ * @param[in] instance device connection structure to use.
+ * @param[in] ep target endpoint's number.
+ * @param[in] setup Setup stage data (control transfers).
+ * @param[in] data data buffer.
+ * @param[in] size size of the data buffer.
+ * @param[out] rsize bytes actually copied to the buffer.
+ * @return Error code.
+ */
+static inline int usb_device_control_read(usb_device_connection_t *instance,
+    usb_endpoint_t ep, uint64_t setup, void *data, size_t size, size_t *rsize)
+{
+	assert(instance);
+	return usb_hc_read(instance->hc_connection,
+	    instance->address, ep, setup, data, size, rsize);
+}
+/*----------------------------------------------------------------------------*/
+/** Send data to the device.
+ * @param instance device connection structure to use.
+ * @param ep target endpoint's number.
+ * @param setup Setup stage data (control transfers).
+ * @param data data buffer.
+ * @param size size of the data buffer.
+ * @return Error code.
+ */
+static inline int usb_device_control_write(usb_device_connection_t *instance,
+    usb_endpoint_t ep, uint64_t setup, const void *data, size_t size)
+{
+	assert(instance);
+	return usb_hc_write(instance->hc_connection,
+	    instance->address, ep, setup, data, size);
+}
+/*----------------------------------------------------------------------------*/
+/** Wrapper for read calls with no setup stage.
+ * @param[in] instance device connection structure.
+ * @param[in] address USB device address.
+ * @param[in] endpoint USB device endpoint.
+ * @param[in] data Data buffer.
+ * @param[in] size Size of the buffer.
+ * @param[out] real_size Size of the transferred data.
+ * @return Error code.
+ */
+static inline int usb_device_read(usb_device_connection_t *instance,
+    usb_endpoint_t ep, void *data, size_t size, size_t *real_size)
+{
+	return usb_device_control_read(instance, ep, 0, data, size, real_size);
+}
+/*----------------------------------------------------------------------------*/
+/** Wrapper for write calls with no setup stage.
+ * @param instance device connection structure.
+ * @param address USB device address.
+ * @param endpoint USB device endpoint.
+ * @param data Data buffer.
+ * @param size Size of the buffer.
+ * @return Error code.
+ */
+static inline int usb_device_write(usb_device_connection_t *instance,
+    usb_endpoint_t ep, const void *data, size_t size)
+{
+	return usb_device_control_write(instance, ep, 0, data, size);
+}
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/src/altiface.c
===================================================================
--- uspace/lib/usbdev/src/altiface.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbdev/src/altiface.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -167,9 +167,13 @@
 }
 
-void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *alternate)
+/** Clean initialized structure.
+ * @param instance structure do deinitialize.
+ */
+void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *instance)
 {
-	if (!alternate)
+	if (!instance)
 		return;
-	free(alternate->alternatives);
+	free(instance->alternatives);
+	instance->alternatives = NULL;
 }
 /**
Index: uspace/lib/usbdev/src/devdrv.c
===================================================================
--- uspace/lib/usbdev/src/devdrv.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbdev/src/devdrv.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
  *
@@ -26,5 +27,4 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup libusbdev
  * @{
@@ -36,5 +36,5 @@
 #include <usb/dev/request.h>
 #include <usb/debug.h>
-#include <usb/dev/dp.h>
+#include <usb/dev.h>
 #include <errno.h>
 #include <str_error.h>
@@ -56,5 +56,4 @@
 static const usb_driver_t *driver = NULL;
 
-
 /** Main routine of USB device driver.
  *
@@ -75,5 +74,5 @@
 	return ddf_driver_main(&generic_driver);
 }
-
+/*----------------------------------------------------------------------------*/
 /** Count number of pipes the driver expects.
  *
@@ -85,40 +84,6 @@
 {
 	size_t count;
-	for (count = 0; endpoints && endpoints[count] != NULL; ++count);
+	for (count = 0; endpoints != NULL && endpoints[count] != NULL; ++count);
 	return count;
-}
-
-/** Initialize endpoint pipes, excluding default control one.
- *
- * @param drv The device driver.
- * @param dev Device to be initialized.
- * @return Error code.
- */
-static int initialize_other_pipes(const usb_endpoint_description_t **endpoints,
-    usb_device_t *dev, int alternate_setting)
-{
-	assert(dev);
-
-	if (endpoints == NULL) {
-		dev->pipes = NULL;
-		dev->pipes_count = 0;
-		return EOK;
-	}
-
-	usb_endpoint_mapping_t *pipes;
-	size_t pipes_count;
-
-	int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints,
-	    dev->descriptors.configuration, dev->descriptors.configuration_size,
-	    dev->interface_no, alternate_setting, &pipes, &pipes_count);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	dev->pipes = pipes;
-	dev->pipes_count = pipes_count;
-
-	return EOK;
 }
 /*----------------------------------------------------------------------------*/
@@ -136,4 +101,5 @@
 	assert(driver->ops->device_add);
 
+	/* Get place for driver data. */
 	usb_device_t *dev = ddf_dev_data_alloc(gen_dev, sizeof(usb_device_t));
 	if (dev == NULL) {
@@ -142,4 +108,6 @@
 		return ENOMEM;
 	}
+
+	/* Initialize generic USB driver data. */
 	const char *err_msg = NULL;
 	int rc = usb_device_init(dev, gen_dev, driver->endpoints, &err_msg);
@@ -150,4 +118,5 @@
 	}
 
+	/* Start USB driver specific initialization. */
 	rc = driver->ops->device_add(dev);
 	if (rc != EOK)
@@ -169,6 +138,11 @@
 	if (driver->ops->device_rem == NULL)
 		return ENOTSUP;
-	/* Just tell the driver to stop whatever it is doing, keep structures */
-	return driver->ops->device_rem(gen_dev->driver_data);
+	/* Just tell the driver to stop whatever it is doing */
+	usb_device_t *usb_dev = gen_dev->driver_data;
+	const int ret = driver->ops->device_rem(usb_dev);
+	if (ret != EOK)
+		return ret;
+	usb_device_deinit(usb_dev);
+	return EOK;
 }
 /*----------------------------------------------------------------------------*/
@@ -197,20 +171,12 @@
  *
  * @param dev Device where to destroy the pipes.
- * @return Error code.
- */
-static int destroy_current_pipes(usb_device_t *dev)
-{
-	int rc = usb_device_destroy_pipes(dev->ddf_dev,
-	    dev->pipes, dev->pipes_count);
-	if (rc != EOK) {
-		return rc;
-	}
-
+ */
+static void destroy_current_pipes(usb_device_t *dev)
+{
+	usb_device_destroy_pipes(dev->pipes, dev->pipes_count);
 	dev->pipes = NULL;
 	dev->pipes_count = 0;
-
-	return EOK;
-}
-
+}
+/*----------------------------------------------------------------------------*/
 /** Change interface setting of a device.
  * This function selects new alternate setting of an interface by issuing
@@ -242,14 +208,9 @@
 	}
 
-	int rc;
-
 	/* Destroy existing pipes. */
-	rc = destroy_current_pipes(dev);
-	if (rc != EOK) {
-		return rc;
-	}
+	destroy_current_pipes(dev);
 
 	/* Change the interface itself. */
-	rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
+	int rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
 	    alternate_setting);
 	if (rc != EOK) {
@@ -258,5 +219,8 @@
 
 	/* Create new pipes. */
-	rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting);
+	rc = usb_device_create_pipes(&dev->wire, endpoints,
+	    dev->descriptors.configuration, dev->descriptors.configuration_size,
+	    dev->interface_no, (int)alternate_setting,
+	    &dev->pipes, &dev->pipes_count);
 
 	return rc;
@@ -316,5 +280,4 @@
  * - registers endpoints with the host controller
  *
- * @param[in] dev Generic DDF device backing the USB one.
  * @param[in] wire Initialized backing connection to the host controller.
  * @param[in] endpoints Endpoints description, NULL terminated.
@@ -329,5 +292,5 @@
  * @return Error code.
  */
-int usb_device_create_pipes(const ddf_dev_t *dev, usb_device_connection_t *wire,
+int usb_device_create_pipes(usb_device_connection_t *wire,
     const usb_endpoint_description_t **endpoints,
     const uint8_t *config_descr, size_t config_descr_size,
@@ -335,7 +298,5 @@
     usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)
 {
-	assert(dev != NULL);
 	assert(wire != NULL);
-	assert(endpoints != NULL);
 	assert(config_descr != NULL);
 	assert(config_descr_size > 0);
@@ -359,5 +320,5 @@
 	}
 
-	/* Now allocate and fully initialize. */
+	/* Now initialize. */
 	for (i = 0; i < pipe_count; i++) {
 		pipes[i].description = endpoints[i];
@@ -370,23 +331,13 @@
 	    config_descr, config_descr_size, wire);
 	if (rc != EOK) {
-		goto rollback_free_only;
-	}
-
-	/* Register the endpoints with HC. */
-	usb_hc_connection_t hc_conn;
-	rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
-	if (rc != EOK) {
-		goto rollback_free_only;
-	}
-
-	rc = usb_hc_connection_open(&hc_conn);
-	if (rc != EOK) {
-		goto rollback_free_only;
-	}
-
+		free(pipes);
+		return rc;
+	}
+
+	/* Register created pipes. */
 	for (i = 0; i < pipe_count; i++) {
 		if (pipes[i].present) {
 			rc = usb_pipe_register(&pipes[i].pipe,
-			    pipes[i].descriptor->poll_interval, &hc_conn);
+			    pipes[i].descriptor->poll_interval);
 			if (rc != EOK) {
 				goto rollback_unregister_endpoints;
@@ -394,8 +345,4 @@
 		}
 	}
-
-	if (usb_hc_connection_close(&hc_conn) != EOK)
-		usb_log_warning("%s: Failed to close connection.\n",
-		    __FUNCTION__);
 
 	*pipes_ptr = pipes;
@@ -415,20 +362,9 @@
 	for (i = 0; i < pipe_count; i++) {
 		if (pipes[i].present) {
-			usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
+			usb_pipe_unregister(&pipes[i].pipe);
 		}
 	}
 
-	if (usb_hc_connection_close(&hc_conn) != EOK)
-		usb_log_warning("usb_device_create_pipes(): "
-		    "Failed to close connection.\n");
-
-	/*
-	 * Jump here if something went wrong before some actual communication
-	 * with HC. Then the only thing that needs to be done is to free
-	 * allocated memory.
-	 */
-rollback_free_only:
 	free(pipes);
-
 	return rc;
 }
@@ -436,48 +372,18 @@
 /** Destroy pipes previously created by usb_device_create_pipes.
  *
- * @param[in] dev Generic DDF device backing the USB one.
  * @param[in] pipes Endpoint mapping to be destroyed.
  * @param[in] pipes_count Number of endpoints.
  */
-int usb_device_destroy_pipes(const ddf_dev_t *dev,
-    usb_endpoint_mapping_t *pipes, size_t pipes_count)
-{
-	assert(dev != NULL);
-
-	if (pipes_count == 0) {
-		assert(pipes == NULL);
-		return EOK;
-	}
-	assert(pipes != NULL);
-
-	int rc;
-
-	/* Prepare connection to HC to allow endpoint unregistering. */
-	usb_hc_connection_t hc_conn;
-	rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
-	if (rc != EOK) {
-		return rc;
-	}
-	rc = usb_hc_connection_open(&hc_conn);
-	if (rc != EOK) {
-		return rc;
-	}
-
+void usb_device_destroy_pipes(usb_endpoint_mapping_t *pipes, size_t pipes_count)
+{
 	/* Destroy the pipes. */
-	size_t i;
-	for (i = 0; i < pipes_count; i++) {
-		usb_log_debug2("Unregistering pipe %zu (%spresent).\n",
+	for (size_t i = 0; i < pipes_count; ++i) {
+		assert(pipes);
+		usb_log_debug2("Unregistering pipe %zu: %spresent.\n",
 		    i, pipes[i].present ? "" : "not ");
 		if (pipes[i].present)
-			usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
-	}
-
-	if (usb_hc_connection_close(&hc_conn) != EOK)
-		usb_log_warning("usb_device_destroy_pipes(): "
-		    "Failed to close connection.\n");
-
+			usb_pipe_unregister(&pipes[i].pipe);
+	}
 	free(pipes);
-
-	return EOK;
 }
 
@@ -505,7 +411,21 @@
 	usb_dev->pipes = NULL;
 
+	/* Get assigned params */
+	devman_handle_t hc_handle;
+	usb_address_t address;
+
+	int rc = usb_get_info_by_handle(ddf_dev->handle,
+	    &hc_handle, &address, &usb_dev->interface_no);
+	if (rc != EOK) {
+		*errstr_ptr = "device parameters retrieval";
+		return rc;
+	}
+
+	/* Initialize hc connection. */
+	usb_hc_connection_initialize(&usb_dev->hc_conn, hc_handle);
+
 	/* Initialize backing wire and control pipe. */
-	int rc = usb_device_connection_initialize_from_device(
-	    &usb_dev->wire, ddf_dev);
+	rc = usb_device_connection_initialize(
+	    &usb_dev->wire, &usb_dev->hc_conn, address);
 	if (rc != EOK) {
 		*errstr_ptr = "device connection initialization";
@@ -515,6 +435,6 @@
 	/* This pipe was registered by the hub driver,
 	 * during device initialization. */
-	rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe,
-	    &usb_dev->wire);
+	rc = usb_pipe_initialize_default_control(
+	    &usb_dev->ctrl_pipe, &usb_dev->wire);
 	if (rc != EOK) {
 		*errstr_ptr = "default control pipe initialization";
@@ -522,12 +442,17 @@
 	}
 
-	/* Get our interface. */
-	usb_dev->interface_no = usb_device_get_assigned_interface(ddf_dev);
+	/* Open hc connection for pipe registration. */
+	rc = usb_hc_connection_open(&usb_dev->hc_conn);
+	if (rc != EOK) {
+		*errstr_ptr = "hc connection open";
+		return rc;
+	}
 
 	/* Retrieve standard descriptors. */
-	rc = usb_device_retrieve_descriptors(&usb_dev->ctrl_pipe,
-	    &usb_dev->descriptors);
+	rc = usb_device_retrieve_descriptors(
+	    &usb_dev->ctrl_pipe, &usb_dev->descriptors);
 	if (rc != EOK) {
 		*errstr_ptr = "descriptor retrieval";
+		usb_hc_connection_close(&usb_dev->hc_conn);
 		return rc;
 	}
@@ -543,7 +468,12 @@
 	    (rc == EOK) ? usb_dev->alternate_interfaces.current : 0;
 
-	/* TODO Add comment here. */
-	rc = initialize_other_pipes(endpoints, usb_dev, alternate_iface);
-	if (rc != EOK) {
+	/* Create and register other pipes than default control (EP 0) */
+	rc = usb_device_create_pipes(&usb_dev->wire, endpoints,
+	    usb_dev->descriptors.configuration,
+	    usb_dev->descriptors.configuration_size,
+	    usb_dev->interface_no, (int)alternate_iface,
+	    &usb_dev->pipes, &usb_dev->pipes_count);
+	if (rc != EOK) {
+		usb_hc_connection_close(&usb_dev->hc_conn);
 		/* Full configuration descriptor is allocated. */
 		usb_device_release_descriptors(&usb_dev->descriptors);
@@ -554,4 +484,5 @@
 	}
 
+	usb_hc_connection_close(&usb_dev->hc_conn);
 	return EOK;
 }
@@ -566,13 +497,20 @@
 {
 	if (dev) {
+		/* Destroy existing pipes. */
+		destroy_current_pipes(dev);
 		/* Ignore errors and hope for the best. */
-		destroy_current_pipes(dev);
-
+		usb_hc_connection_deinitialize(&dev->hc_conn);
 		usb_alternate_interfaces_deinit(&dev->alternate_interfaces);
 		usb_device_release_descriptors(&dev->descriptors);
 		free(dev->driver_data);
-	}
-}
-
+		dev->driver_data = NULL;
+	}
+}
+
+/** Allocate driver specific data.
+ * @param usb_dev usb_device structure.
+ * @param size requested data size.
+ * @return Pointer to the newly allocated space, NULL on failure.
+ */
 void * usb_device_data_alloc(usb_device_t *usb_dev, size_t size)
 {
Index: uspace/lib/usbdev/src/devpoll.c
===================================================================
--- uspace/lib/usbdev/src/devpoll.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbdev/src/devpoll.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -46,11 +46,15 @@
 /** Data needed for polling. */
 typedef struct {
+	/** Parameters for automated polling. */
 	usb_device_auto_polling_t auto_polling;
 
+	/** USB device to poll. */
 	usb_device_t *dev;
+	/** Device pipe to use for polling. */
 	size_t pipe_index;
+	/** Size of the recieved data. */
 	size_t request_size;
+	/** Data buffer. */
 	uint8_t *buffer;
-	void *custom_arg;
 } polling_data_t;
 
@@ -119,5 +123,5 @@
 			++failed_attempts;
 			const bool cont = (params->on_error == NULL) ? true :
-			    params->on_error(data->dev, rc, data->custom_arg);
+			    params->on_error(data->dev, rc, params->arg);
 			if (!cont) {
 				failed_attempts = params->max_failures;
@@ -129,5 +133,5 @@
 		assert(params->on_data);
 		const bool carry_on = params->on_data(
-		    data->dev, data->buffer, actual_size, data->custom_arg);
+		    data->dev, data->buffer, actual_size, params->arg);
 
 		if (!carry_on) {
@@ -149,5 +153,5 @@
 
 	if (params->on_polling_end != NULL) {
-		params->on_polling_end(data->dev, failed, data->custom_arg);
+		params->on_polling_end(data->dev, failed, params->arg);
 	}
 
@@ -199,8 +203,9 @@
 		.on_polling_end = terminated_callback,
 		.on_error = NULL,
+		.arg = arg,
 	};
 
 	return usb_device_auto_polling(dev, pipe_index, &auto_polling,
-	   request_size, arg);
+	   request_size);
 }
 
@@ -224,5 +229,5 @@
 int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
     const usb_device_auto_polling_t *polling,
-    size_t request_size, void *arg)
+    size_t request_size)
 {
 	if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) {
@@ -252,5 +257,4 @@
 	polling_data->dev = dev;
 	polling_data->pipe_index = pipe_index;
-	polling_data->custom_arg = arg;
 
 	/* Copy provided settings. */
Index: uspace/lib/usbdev/src/hub.c
===================================================================
--- uspace/lib/usbdev/src/hub.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbdev/src/hub.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -38,5 +38,4 @@
 #include <usb/dev/recognise.h>
 #include <usb/debug.h>
-#include <usbhc_iface.h>
 #include <errno.h>
 #include <assert.h>
@@ -45,46 +44,8 @@
 #include <async.h>
 
-/** How much time to wait between attempts to register endpoint 0:0.
+/** How much time to wait between attempts to get the default address.
  * The value is based on typical value for port reset + some overhead.
  */
-#define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2))
-
-/** Check that HC connection is alright.
- *
- * @param conn Connection to be checked.
- */
-#define CHECK_CONNECTION(conn) \
-	do { \
-		assert((conn)); \
-		if (!usb_hc_connection_is_opened((conn))) { \
-			usb_log_error("Connection not open.\n"); \
-			return ENOTCONN; \
-		} \
-	} while (false)
-
-/** Ask host controller for free address assignment.
- *
- * @param connection Opened connection to host controller.
- * @param preferred Preferred SUB address.
- * @param strict Fail if the preferred address is not avialable.
- * @param speed Speed of the new device (device that will be assigned
- *    the returned address).
- * @return Assigned USB address or negative error code.
- */
-usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
-    usb_address_t preferred, bool strict, usb_speed_t speed)
-{
-	CHECK_CONNECTION(connection);
-
-	async_exch_t *exch = async_exchange_begin(connection->hc_sess);
-	if (!exch)
-		return (usb_address_t)ENOMEM;
-
-	usb_address_t address = preferred;
-	const int ret = usbhc_request_address(exch, &address, strict, speed);
-
-	async_exchange_end(exch);
-	return ret == EOK ? address : ret;
-}
+#define DEFAULT_ADDRESS_ATTEMPT_DELAY_USEC (1000 * (10 + 2))
 
 /** Inform host controller about new device.
@@ -94,39 +55,12 @@
  * @return Error code.
  */
-int usb_hc_register_device(usb_hc_connection_t *connection,
+int usb_hub_register_device(usb_hc_connection_t *connection,
     const usb_hub_attached_device_t *attached_device)
 {
-	CHECK_CONNECTION(connection);
+	assert(connection);
 	if (attached_device == NULL || attached_device->fun == NULL)
-		return EINVAL;
-
-	async_exch_t *exch = async_exchange_begin(connection->hc_sess);
-	if (!exch)
-		return ENOMEM;
-	const int ret = usbhc_bind_address(exch,
+		return EBADMEM;
+	return usb_hc_bind_address(connection,
 	    attached_device->address, attached_device->fun->handle);
-	async_exchange_end(exch);
-
-	return ret;
-}
-
-/** Inform host controller about device removal.
- *
- * @param connection Opened connection to host controller.
- * @param address Address of the device that is being removed.
- * @return Error code.
- */
-int usb_hc_unregister_device(usb_hc_connection_t *connection,
-    usb_address_t address)
-{
-	CHECK_CONNECTION(connection);
-
-	async_exch_t *exch = async_exchange_begin(connection->hc_sess);
-	if (!exch)
-		return ENOMEM;
-	const int ret = usbhc_release_address(exch, address);
-	async_exchange_end(exch);
-
-	return ret;
 }
 
@@ -145,6 +79,5 @@
  * @return Error code.
  */
-static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address,
-    usb_hc_connection_t *hc_conn)
+static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address)
 {
 	if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
@@ -152,5 +85,4 @@
 	}
 	assert(pipe);
-	assert(hc_conn);
 	assert(pipe->wire != NULL);
 
@@ -166,11 +98,15 @@
 
 	/* TODO: prevent others from accessing the wire now. */
-	if (usb_pipe_unregister(pipe, hc_conn) != EOK) {
+	if (usb_pipe_unregister(pipe) != EOK) {
 		usb_log_warning(
 		    "Failed to unregister the old pipe on address change.\n");
 	}
+	/* Address changed. We can release the old one, thus
+	 * allowing other to us it. */
+	usb_hc_release_address(pipe->wire->hc_connection, pipe->wire->address);
+
 	/* The address is already changed so set it in the wire */
 	pipe->wire->address = new_address;
-	rc = usb_pipe_register(pipe, 0, hc_conn);
+	rc = usb_pipe_register(pipe, 0);
 	if (rc != EOK)
 		return EADDRNOTAVAIL;
@@ -220,14 +156,10 @@
  */
 int usb_hc_new_device_wrapper(ddf_dev_t *parent,
-    usb_hc_connection_t *connection, usb_speed_t dev_speed,
+    usb_hc_connection_t *hc_conn, usb_speed_t dev_speed,
     int (*enable_port)(void *arg), void *arg, usb_address_t *assigned_address,
     ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
 {
-	if (new_fun == NULL || connection == NULL)
+	if (new_fun == NULL || hc_conn == NULL)
 		return EINVAL;
-
-	// TODO: Why not use provided connection?
-	usb_hc_connection_t hc_conn;
-	usb_hc_connection_initialize(&hc_conn, connection->hc_handle);
 
 	int rc;
@@ -239,14 +171,13 @@
 	}
 
-	rc = usb_hc_connection_open(&hc_conn);
+	/* We are gona do a lot of communication better open it in advance. */
+	rc = usb_hc_connection_open(hc_conn);
 	if (rc != EOK) {
 		return rc;
 	}
 
-	/*
-	 * Request new address.
-	 */
+	/* Request a new address. */
 	usb_address_t dev_addr =
-	    usb_hc_request_address(&hc_conn, 0, false, dev_speed);
+	    usb_hc_request_address(hc_conn, 0, false, dev_speed);
 	if (dev_addr < 0) {
 		rc = EADDRNOTAVAIL;
@@ -254,31 +185,33 @@
 	}
 
+	/* Initialize connection to device. */
+	usb_device_connection_t dev_conn;
+	rc = usb_device_connection_initialize(
+	    &dev_conn, hc_conn, USB_ADDRESS_DEFAULT);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_free_address;
+	}
+
+	/* Initialize control pipe on default address. Don't register yet. */
+	usb_pipe_t ctrl_pipe;
+	rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_free_address;
+	}
+
 	/*
-	 * We will not register control pipe on default address.
-	 * The registration might fail. That means that someone else already
-	 * registered that endpoint. We will simply wait and try again.
+	 * The default address request might fail.
+	 * That means that someone else is already using that address.
+	 * We will simply wait and try again.
 	 * (Someone else already wants to add a new device.)
 	 */
-	usb_device_connection_t dev_conn;
-	rc = usb_device_connection_initialize_on_default_address(&dev_conn,
-	    &hc_conn);
-	if (rc != EOK) {
-		rc = ENOTCONN;
-		goto leave_release_free_address;
-	}
-
-	usb_pipe_t ctrl_pipe;
-	rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
-	if (rc != EOK) {
-		rc = ENOTCONN;
-		goto leave_release_free_address;
-	}
-
 	do {
-		rc = usb_hc_request_address(&hc_conn, USB_ADDRESS_DEFAULT,
+		rc = usb_hc_request_address(hc_conn, USB_ADDRESS_DEFAULT,
 		    true, dev_speed);
 		if (rc == ENOENT) {
 			/* Do not overheat the CPU ;-). */
-			async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC);
+			async_usleep(DEFAULT_ADDRESS_ATTEMPT_DELAY_USEC);
 		}
 	} while (rc == ENOENT);
@@ -287,6 +220,6 @@
 	}
 
-	/* Register control pipe on default address. */
-	rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
+	/* Register control pipe on default address. 0 means no interval. */
+	rc = usb_pipe_register(&ctrl_pipe, 0);
 	if (rc != EOK) {
 		rc = ENOTCONN;
@@ -295,5 +228,4 @@
 
 	struct timeval end_time;
-
 	rc = gettimeofday(&end_time, NULL);
 	if (rc != EOK) {
@@ -330,5 +262,5 @@
 	}
 
-	rc = usb_request_set_address(&ctrl_pipe, dev_addr, &hc_conn);
+	rc = usb_request_set_address(&ctrl_pipe, dev_addr);
 	if (rc != EOK) {
 		rc = ESTALL;
@@ -336,7 +268,4 @@
 	}
 
-	/* Address changed. We can release the default, thus
-	 * allowing other to access the default address. */
-	usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
 
 	/* Register the device with devman. */
@@ -356,5 +285,5 @@
 
 	/* Inform the host controller about the handle. */
-	rc = usb_hc_register_device(&hc_conn, &new_device);
+	rc = usb_hub_register_device(hc_conn, &new_device);
 	if (rc != EOK) {
 		/* We know nothing about that data. */
@@ -381,18 +310,20 @@
 	 */
 leave_release_default_address:
-	usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
+	if (usb_hc_release_address(hc_conn, USB_ADDRESS_DEFAULT) != EOK)
+		usb_log_warning("%s: Failed to release defaut address.\n",
+		    __FUNCTION__);
 
 leave_release_free_address:
 	/* This might be either 0:0 or dev_addr:0 */
-	if (usb_pipe_unregister(&ctrl_pipe, &hc_conn) != EOK)
+	if (usb_pipe_unregister(&ctrl_pipe) != EOK)
 		usb_log_warning("%s: Failed to unregister default pipe.\n",
 		    __FUNCTION__);
 
-	if (usb_hc_unregister_device(&hc_conn, dev_addr) != EOK)
-		usb_log_warning("%s: Failed to unregister device.\n",
-		    __FUNCTION__);
+	if (usb_hc_release_address(hc_conn, dev_addr) != EOK)
+		usb_log_warning("%s: Failed to release address: %d.\n",
+		    __FUNCTION__, dev_addr);
 
 close_connection:
-	if (usb_hc_connection_close(&hc_conn) != EOK)
+	if (usb_hc_connection_close(hc_conn) != EOK)
 		usb_log_warning("%s: Failed to close hc connection.\n",
 		    __FUNCTION__);
Index: pace/lib/usbdev/src/pipepriv.c
===================================================================
--- uspace/lib/usbdev/src/pipepriv.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ 	(revision )
@@ -1,148 +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 libusbdev
- * @{
- */
-/** @file
- * Library internal functions on USB pipes (implementation).
- */
-#include "pipepriv.h"
-#include <devman.h>
-#include <errno.h>
-#include <assert.h>
-
-/** Ensure exclusive access to the IPC phone of given pipe.
- *
- * @param pipe Pipe to be exclusively accessed.
- */
-void pipe_start_transaction(usb_pipe_t *pipe)
-{
-	fibril_mutex_lock(&pipe->hc_sess_mutex);
-}
-
-/** Terminate exclusive access to the IPC phone of given pipe.
- *
- * @param pipe Pipe to be released from exclusive usage.
- */
-void pipe_end_transaction(usb_pipe_t *pipe)
-{
-	fibril_mutex_unlock(&pipe->hc_sess_mutex);
-}
-
-/** Ensure exclusive access to the pipe as a whole.
- *
- * @param pipe Pipe to be exclusively accessed.
- */
-void pipe_acquire(usb_pipe_t *pipe)
-{
-	fibril_mutex_lock(&pipe->guard);
-}
-
-/** Terminate exclusive access to the pipe as a whole.
- *
- * @param pipe Pipe to be released from exclusive usage.
- */
-void pipe_release(usb_pipe_t *pipe)
-{
-	fibril_mutex_unlock(&pipe->guard);
-}
-
-/** Add reference of active transfers over the pipe.
- *
- * @param pipe The USB pipe.
- * @param hide_failure Whether to hide failure when adding reference
- *	(use soft refcount).
- * @return Error code.
- * @retval EOK Currently always.
- */
-int pipe_add_ref(usb_pipe_t *pipe, bool hide_failure)
-{
-	pipe_acquire(pipe);
-	
-	if (pipe->refcount == 0) {
-		assert(pipe->hc_sess == NULL);
-		/* Need to open the phone by ourselves. */
-		async_sess_t *sess =
-		    devman_device_connect(EXCHANGE_SERIALIZE, pipe->wire->hc_handle, 0);
-		if (!sess) {
-			if (hide_failure) {
-				pipe->refcount_soft++;
-				pipe_release(pipe);
-				return EOK;
-			}
-			
-			pipe_release(pipe);
-			return ENOMEM;
-		}
-		
-		/*
-		 * No locking is needed, refcount is zero and whole pipe
-		 * mutex is locked.
-		 */
-		
-		pipe->hc_sess = sess;
-	}
-	
-	pipe->refcount++;
-	pipe_release(pipe);
-	
-	return EOK;
-}
-
-/** Drop active transfer reference on the pipe.
- *
- * @param pipe The USB pipe.
- */
-void pipe_drop_ref(usb_pipe_t *pipe)
-{
-	pipe_acquire(pipe);
-	
-	if (pipe->refcount_soft > 0) {
-		pipe->refcount_soft--;
-		pipe_release(pipe);
-		return;
-	}
-	
-	assert(pipe->refcount > 0);
-	
-	pipe->refcount--;
-	
-	if (pipe->refcount == 0) {
-		/* We were the last users, let's hang-up. */
-		async_hangup(pipe->hc_sess);
-		pipe->hc_sess = NULL;
-	}
-	
-	pipe_release(pipe);
-}
-
-
-/**
- * @}
- */
Index: pace/lib/usbdev/src/pipepriv.h
===================================================================
--- uspace/lib/usbdev/src/pipepriv.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ 	(revision )
@@ -1,54 +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 libusbdev
- * @{
- */
-/** @file
- * Library internal functions on USB pipes.
- */
-#ifndef LIBUSBDEV_PIPEPRIV_H_
-#define LIBUSBDEV_PIPEPRIV_H_
-
-#include <usb/dev/pipes.h>
-#include <bool.h>
-
-void pipe_acquire(usb_pipe_t *);
-void pipe_release(usb_pipe_t *);
-
-void pipe_start_transaction(usb_pipe_t *);
-void pipe_end_transaction(usb_pipe_t *);
-
-int pipe_add_ref(usb_pipe_t *, bool);
-void pipe_drop_ref(usb_pipe_t *);
-
-
-#endif
-/**
- * @}
- */
Index: uspace/lib/usbdev/src/pipes.c
===================================================================
--- uspace/lib/usbdev/src/pipes.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbdev/src/pipes.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
  *
@@ -26,198 +27,313 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup libusbdev
  * @{
  */
 /** @file
- * USB endpoint pipes miscellaneous functions.
- */
-#include <usb/usb.h>
+ * USB endpoint pipes functions.
+ */
 #include <usb/dev/pipes.h>
-#include <usb/debug.h>
-#include <usb/hc.h>
-#include <usbhc_iface.h>
-#include <usb_iface.h>
-#include <devman.h>
+#include <usb/dev/request.h>
 #include <errno.h>
 #include <assert.h>
-#include "pipepriv.h"
-
-#define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */
-
-/** Tell USB address assigned to given device.
- *
- * @param sess Session to parent device.
- * @param dev Device in question.
- * @return USB address or error code.
- */
-static usb_address_t get_my_address(async_sess_t *sess, const ddf_dev_t *dev)
-{
-	assert(sess);
-	async_exch_t *exch = async_exchange_begin(sess);
-	if (!exch)
-		return ENOMEM;
-
-	usb_address_t address;
-	const int ret = usb_get_my_address(exch, &address);
-
-	async_exchange_end(exch);
-
-	return (ret == EOK) ? address : ret;
-}
-
-/** Tell USB interface assigned to given device.
- *
- * @param device Device in question.
- * @return Error code (ENOTSUP means any).
- */
-int usb_device_get_assigned_interface(const ddf_dev_t *device)
-{
-	assert(device);
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_ATOMIC, device->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-
-	async_exch_t *exch = async_exchange_begin(parent_sess);
-	if (!exch) {
-		async_hangup(parent_sess);
-		return ENOMEM;
-	}
-
-	int iface_no;
-	const int ret = usb_get_my_interface(exch, &iface_no);
-
-	return ret == EOK ? iface_no : ret;
-}
-
-/** Initialize connection to USB device.
- *
- * @param connection Connection structure to be initialized.
- * @param dev Generic device backing the USB device.
- * @return Error code.
- */
-int usb_device_connection_initialize_from_device(
-    usb_device_connection_t *connection, const ddf_dev_t *dev)
-{
+
+/** Prepare pipe for a long transfer.
+ *
+ * Long transfer is transfer consisting of several requests to the HC.
+ * Calling this function is optional and it has positive effect of
+ * improved performance because IPC session is initiated only once.
+ *
+ * @param pipe Pipe over which the transfer will happen.
+ * @return Error code.
+ */
+int usb_pipe_start_long_transfer(usb_pipe_t *pipe)
+{
+	assert(pipe);
+	assert(pipe->wire);
+	assert(pipe->wire->hc_connection);
+	return usb_hc_connection_open(pipe->wire->hc_connection);
+}
+/*----------------------------------------------------------------------------*/
+/** Terminate a long transfer on a pipe.
+ * @param pipe Pipe where to end the long transfer.
+ * @return Error code.
+ * @see usb_pipe_start_long_transfer
+ */
+int usb_pipe_end_long_transfer(usb_pipe_t *pipe)
+{
+	assert(pipe);
+	assert(pipe->wire);
+	assert(pipe->wire->hc_connection);
+	return usb_hc_connection_close(pipe->wire->hc_connection);
+}
+/*----------------------------------------------------------------------------*/
+/** Try to clear endpoint halt of default control pipe.
+ *
+ * @param pipe Pipe for control endpoint zero.
+ */
+static void clear_self_endpoint_halt(usb_pipe_t *pipe)
+{
+	assert(pipe != NULL);
+
+	if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
+		return;
+	}
+
+	/* Prevent infinite recursion. */
+	pipe->auto_reset_halt = false;
+	usb_request_clear_endpoint_halt(pipe, 0);
+	pipe->auto_reset_halt = true;
+}
+/*----------------------------------------------------------------------------*/
+/** Request a control read transfer on an endpoint pipe.
+ *
+ * This function encapsulates all three stages of a control transfer.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[out] data_buffer Buffer for incoming data.
+ * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
+ * @param[out] data_transfered_size Number of bytes that were actually
+ *                                  transfered during the DATA stage.
+ * @return Error code.
+ */
+int usb_pipe_control_read(usb_pipe_t *pipe,
+    const void *setup_buffer, size_t setup_buffer_size,
+    void *buffer, size_t buffer_size, size_t *transfered_size)
+{
+	assert(pipe);
+
+	if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
+		return EINVAL;
+	}
+
+	if ((buffer == NULL) || (buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if ((pipe->direction != USB_DIRECTION_BOTH)
+	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
+		return EBADF;
+	}
+
+	uint64_t setup_packet;
+	memcpy(&setup_packet, setup_buffer, 8);
+
+	size_t act_size = 0;
+	const int rc = usb_device_control_read(pipe->wire,
+	    pipe->endpoint_no, setup_packet, buffer, buffer_size, &act_size);
+
+	if (rc == ESTALL) {
+		clear_self_endpoint_halt(pipe);
+	}
+
+	if (rc == EOK && transfered_size != NULL) {
+		*transfered_size = act_size;
+	}
+
+	return rc;
+}
+/*----------------------------------------------------------------------------*/
+/** Request a control write transfer on an endpoint pipe.
+ *
+ * This function encapsulates all three stages of a control transfer.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[in] data_buffer Buffer with data to be sent.
+ * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
+ * @return Error code.
+ */
+int usb_pipe_control_write(usb_pipe_t *pipe,
+    const void *setup_buffer, size_t setup_buffer_size,
+    const void *buffer, size_t buffer_size)
+{
+	assert(pipe);
+
+	if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
+		return EINVAL;
+	}
+
+	if ((buffer == NULL) && (buffer_size > 0)) {
+		return EINVAL;
+	}
+
+	if ((buffer != NULL) && (buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if ((pipe->direction != USB_DIRECTION_BOTH)
+	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
+		return EBADF;
+	}
+
+	uint64_t setup_packet;
+	memcpy(&setup_packet, setup_buffer, 8);
+
+	const int rc = usb_device_control_write(pipe->wire,
+	    pipe->endpoint_no, setup_packet, buffer, buffer_size);
+
+	if (rc == ESTALL) {
+		clear_self_endpoint_halt(pipe);
+	}
+
+	return rc;
+}
+/*----------------------------------------------------------------------------*/
+/** Request a read (in) transfer on an endpoint pipe.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[out] buffer Buffer where to store the data.
+ * @param[in] size Size of the buffer (in bytes).
+ * @param[out] size_transfered Number of bytes that were actually transfered.
+ * @return Error code.
+ */
+int usb_pipe_read(usb_pipe_t *pipe,
+    void *buffer, size_t size, size_t *size_transfered)
+{
+	assert(pipe);
+
+	if (buffer == NULL) {
+		return EINVAL;
+	}
+
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	if (pipe->direction != USB_DIRECTION_IN) {
+		return EBADF;
+	}
+
+	if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
+		return EBADF;
+	}
+
+	/* Isochronous transfer are not supported (yet) */
+	if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
+	    pipe->transfer_type != USB_TRANSFER_BULK)
+	    return ENOTSUP;
+
+	size_t act_size = 0;
+	const int rc = usb_device_read(pipe->wire,
+	    pipe->endpoint_no, buffer, size, &act_size);
+
+	if (rc == EOK && size_transfered != NULL) {
+		*size_transfered = act_size;
+	}
+
+	return rc;
+}
+/*----------------------------------------------------------------------------*/
+/** Request a write (out) transfer on an endpoint pipe.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] buffer Buffer with data to transfer.
+ * @param[in] size Size of the buffer (in bytes).
+ * @return Error code.
+ */
+int usb_pipe_write(usb_pipe_t *pipe, const void *buffer, size_t size)
+{
+	assert(pipe);
+
+	if (buffer == NULL || size == 0) {
+		return EINVAL;
+	}
+
+	if (pipe->direction != USB_DIRECTION_OUT) {
+		return EBADF;
+	}
+
+	if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
+		return EBADF;
+	}
+
+	/* Isochronous transfer are not supported (yet) */
+	if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
+	    pipe->transfer_type != USB_TRANSFER_BULK)
+	    return ENOTSUP;
+
+	return usb_device_write(pipe->wire,
+	    pipe->endpoint_no, buffer, size);
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize USB endpoint pipe.
+ *
+ * @param pipe Endpoint pipe to be initialized.
+ * @param connection Connection to the USB device backing this pipe (the wire).
+ * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
+ * @param transfer_type Transfer type (e.g. interrupt or bulk).
+ * @param max_packet_size Maximum packet size in bytes.
+ * @param direction Endpoint direction (in/out).
+ * @return Error code.
+ */
+int usb_pipe_initialize(usb_pipe_t *pipe,
+    usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
+    usb_transfer_type_t transfer_type, size_t max_packet_size,
+    usb_direction_t direction)
+{
+	assert(pipe);
 	assert(connection);
-	assert(dev);
-	
-	int rc;
-	devman_handle_t hc_handle;
-	usb_address_t my_address;
-	
-	rc = usb_hc_find(dev->handle, &hc_handle);
-	if (rc != EOK)
-		return rc;
-	
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_ATOMIC, dev->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-	
-	/*
-	 * Asking for "my" address may require several attempts.
-	 * That is because following scenario may happen:
-	 *  - parent driver (i.e. driver of parent device) announces new device
-	 *    and devman launches current driver
-	 *  - parent driver is preempted and thus does not send address-handle
-	 *    binding to HC driver
-	 *  - this driver gets here and wants the binding
-	 *  - the HC does not know the binding yet and thus it answers ENOENT
-	 *  So, we need to wait for the HC to learn the binding.
-	 */
-	
-	do {
-		my_address = get_my_address(parent_sess, dev);
-		
-		if (my_address == ENOENT) {
-			/* Be nice, let other fibrils run and try again. */
-			async_usleep(IPC_AGAIN_DELAY);
-		} else if (my_address < 0) {
-			/* Some other problem, no sense trying again. */
-			rc = my_address;
-			goto leave;
-		}
-	
-	} while (my_address < 0);
-	
-	rc = usb_device_connection_initialize(connection,
-	    hc_handle, my_address);
-	
-leave:
-	async_hangup(parent_sess);
+
+	pipe->wire = connection;
+	pipe->endpoint_no = endpoint_no;
+	pipe->transfer_type = transfer_type;
+	pipe->max_packet_size = max_packet_size;
+	pipe->direction = direction;
+	pipe->auto_reset_halt = false;
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize USB endpoint pipe as the default zero control pipe.
+ *
+ * @param pipe Endpoint pipe to be initialized.
+ * @param connection Connection to the USB device backing this pipe (the wire).
+ * @return Error code.
+ */
+int usb_pipe_initialize_default_control(usb_pipe_t *pipe,
+    usb_device_connection_t *connection)
+{
+	assert(pipe);
+	assert(connection);
+
+	int rc = usb_pipe_initialize(pipe, connection, 0, USB_TRANSFER_CONTROL,
+	    CTRL_PIPE_MIN_PACKET_SIZE, USB_DIRECTION_BOTH);
+
+	pipe->auto_reset_halt = true;
+
 	return rc;
 }
-
-/** Initialize connection to USB device.
- *
- * @param connection Connection structure to be initialized.
- * @param host_controller_handle Devman handle of host controller device is
- * 	connected to.
- * @param device_address Device USB address.
- * @return Error code.
- */
-int usb_device_connection_initialize(usb_device_connection_t *connection,
-    devman_handle_t host_controller_handle, usb_address_t device_address)
-{
-	assert(connection);
-
-	if ((device_address < 0) || (device_address >= USB11_ADDRESS_MAX)) {
-		return EINVAL;
-	}
-
-	connection->hc_handle = host_controller_handle;
-	connection->address = device_address;
-
-	return EOK;
-}
-
-/** Initialize connection to USB device on default address.
- *
- * @param dev_connection Device connection structure to be initialized.
- * @param hc_connection Initialized connection to host controller.
- * @return Error code.
- */
-int usb_device_connection_initialize_on_default_address(
-    usb_device_connection_t *dev_connection,
-    usb_hc_connection_t *hc_connection)
-{
-	assert(dev_connection);
-
-	if (hc_connection == NULL) {
-		return EBADMEM;
-	}
-
-	return usb_device_connection_initialize(dev_connection,
-	    hc_connection->hc_handle, (usb_address_t) 0);
-}
-
-/** Prepare pipe for a long transfer.
- *
- * By a long transfer is mean transfer consisting of several
- * requests to the HC.
- * Calling such function is optional and it has positive effect of
- * improved performance because IPC session is initiated only once.
- *
- * @param pipe Pipe over which the transfer will happen.
- * @return Error code.
- */
-void usb_pipe_start_long_transfer(usb_pipe_t *pipe)
-{
-	(void) pipe_add_ref(pipe, true);
-}
-
-/** Terminate a long transfer on a pipe.
- *
- * @see usb_pipe_start_long_transfer
- *
- * @param pipe Pipe where to end the long transfer.
- */
-void usb_pipe_end_long_transfer(usb_pipe_t *pipe)
-{
-	pipe_drop_ref(pipe);
+/*----------------------------------------------------------------------------*/
+/** Register endpoint with the host controller.
+ *
+ * @param pipe Pipe to be registered.
+ * @param interval Polling interval.
+ * @return Error code.
+ */
+int usb_pipe_register(usb_pipe_t *pipe, unsigned interval)
+{
+	assert(pipe);
+	assert(pipe->wire);
+
+	return usb_device_register_endpoint(pipe->wire,
+	   pipe->endpoint_no, pipe->transfer_type,
+	   pipe->direction, pipe->max_packet_size, interval);
+}
+/*----------------------------------------------------------------------------*/
+/** Revert endpoint registration with the host controller.
+ *
+ * @param pipe Pipe to be unregistered.
+ * @return Error code.
+ */
+int usb_pipe_unregister(usb_pipe_t *pipe)
+{
+	assert(pipe);
+	assert(pipe->wire);
+
+	return usb_device_unregister_endpoint(pipe->wire,
+	    pipe->endpoint_no, pipe->direction);
 }
 
Index: uspace/lib/usbdev/src/pipesinit.c
===================================================================
--- uspace/lib/usbdev/src/pipesinit.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbdev/src/pipesinit.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -31,5 +31,5 @@
  */
 /** @file
- * Initialization of endpoint pipes.
+ * Non trivial initialization of endpoint pipes.
  *
  */
@@ -38,11 +38,8 @@
 #include <usb/dev/dp.h>
 #include <usb/dev/request.h>
-#include <usbhc_iface.h>
 #include <errno.h>
 #include <assert.h>
 
-#define CTRL_PIPE_MIN_PACKET_SIZE 8
 #define DEV_DESCR_MAX_PACKET_SIZE_OFFSET 7
-
 
 #define NESTING(parentname, childname) \
@@ -327,59 +324,4 @@
 
 	return EOK;
-}
-
-/** Initialize USB endpoint pipe.
- *
- * @param pipe Endpoint pipe to be initialized.
- * @param connection Connection to the USB device backing this pipe (the wire).
- * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
- * @param transfer_type Transfer type (e.g. interrupt or bulk).
- * @param max_packet_size Maximum packet size in bytes.
- * @param direction Endpoint direction (in/out).
- * @return Error code.
- */
-int usb_pipe_initialize(usb_pipe_t *pipe,
-    usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
-    usb_transfer_type_t transfer_type, size_t max_packet_size,
-    usb_direction_t direction)
-{
-	assert(pipe);
-	assert(connection);
-
-	fibril_mutex_initialize(&pipe->guard);
-	pipe->wire = connection;
-	pipe->hc_sess = NULL;
-	fibril_mutex_initialize(&pipe->hc_sess_mutex);
-	pipe->endpoint_no = endpoint_no;
-	pipe->transfer_type = transfer_type;
-	pipe->max_packet_size = max_packet_size;
-	pipe->direction = direction;
-	pipe->refcount = 0;
-	pipe->refcount_soft = 0;
-	pipe->auto_reset_halt = false;
-
-	return EOK;
-}
-
-
-/** Initialize USB endpoint pipe as the default zero control pipe.
- *
- * @param pipe Endpoint pipe to be initialized.
- * @param connection Connection to the USB device backing this pipe (the wire).
- * @return Error code.
- */
-int usb_pipe_initialize_default_control(usb_pipe_t *pipe,
-    usb_device_connection_t *connection)
-{
-	assert(pipe);
-	assert(connection);
-
-	int rc = usb_pipe_initialize(pipe, connection,
-	    0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
-	    USB_DIRECTION_BOTH);
-
-	pipe->auto_reset_halt = true;
-
-	return rc;
 }
 
@@ -435,57 +377,4 @@
 }
 
-/** Register endpoint with the host controller.
- *
- * @param pipe Pipe to be registered.
- * @param interval Polling interval.
- * @param hc_connection Connection to the host controller (must be opened).
- * @return Error code.
- */
-int usb_pipe_register(usb_pipe_t *pipe, unsigned interval,
-    usb_hc_connection_t *hc_connection)
-{
-	assert(pipe);
-	assert(pipe->wire);
-	assert(hc_connection);
-
-	if (!usb_hc_connection_is_opened(hc_connection))
-		return EBADF;
-	async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
-	if (!exch)
-		return ENOMEM;
-	const int ret = usbhc_register_endpoint(exch,
-	    pipe->wire->address, pipe->endpoint_no, pipe->transfer_type,
-	    pipe->direction, pipe->max_packet_size, interval);
-
-	async_exchange_end(exch);
-	return ret;
-}
-
-/** Revert endpoint registration with the host controller.
- *
- * @param pipe Pipe to be unregistered.
- * @param hc_connection Connection to the host controller (must be opened).
- * @return Error code.
- */
-int usb_pipe_unregister(usb_pipe_t *pipe,
-    usb_hc_connection_t *hc_connection)
-{
-	assert(pipe);
-	assert(pipe->wire);
-	assert(hc_connection);
-
-	if (!usb_hc_connection_is_opened(hc_connection))
-		return EBADF;
-
-	async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
-	if (!exch)
-		return ENOMEM;
-	const int ret = usbhc_unregister_endpoint(exch,
-	    pipe->wire->address, pipe->endpoint_no, pipe->direction);
-	async_exchange_end(exch);
-
-	return ret;
-}
-
 /**
  * @}
Index: pace/lib/usbdev/src/pipesio.c
===================================================================
--- uspace/lib/usbdev/src/pipesio.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ 	(revision )
@@ -1,316 +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 libusbdev
- * @{
- */
-/** @file
- * Input and output functions (reads and writes) on endpoint pipes.
- *
- * Note on synchronousness of the operations: there is ABSOLUTELY NO
- * guarantee that a call to particular function will not trigger a fibril
- * switch.
- *
- * Note about the implementation: the transfer requests are always divided
- * into two functions.
- * The outer one does checking of input parameters (e.g. that session was
- * already started, buffers are not NULL etc), while the inner one
- * (with _no_checks suffix) does the actual IPC (it checks for IPC errors,
- * obviously).
- */
-
-#include <usb/usb.h>
-#include <usb/dev/pipes.h>
-#include <errno.h>
-#include <assert.h>
-#include <usbhc_iface.h>
-#include <usb/dev/request.h>
-#include <async.h>
-#include "pipepriv.h"
-
-/** Request an in transfer, no checking of input parameters.
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[out] buffer Buffer where to store the data.
- * @param[in] size Size of the buffer (in bytes).
- * @param[out] size_transfered Number of bytes that were actually transfered.
- * @return Error code.
- */
-static int usb_pipe_read_no_check(usb_pipe_t *pipe, uint64_t setup,
-    void *buffer, size_t size, size_t *size_transfered)
-{
-	/* Isochronous transfer are not supported (yet) */
-	if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
-	    pipe->transfer_type != USB_TRANSFER_BULK &&
-	    pipe->transfer_type != USB_TRANSFER_CONTROL)
-	    return ENOTSUP;
-
-	int ret = pipe_add_ref(pipe, false);
-	if (ret != EOK) {
-		return ret;
-	}
-
-	/* Ensure serialization over the phone. */
-	pipe_start_transaction(pipe);
-	async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
-	if (!exch) {
-		pipe_end_transaction(pipe);
-		pipe_drop_ref(pipe);
-		return ENOMEM;
-	}
-
-	ret = usbhc_read(exch, pipe->wire->address, pipe->endpoint_no,
-	    setup, buffer, size, size_transfered);
-	async_exchange_end(exch);
-	pipe_end_transaction(pipe);
-	pipe_drop_ref(pipe);
-	return ret;
-}
-
-/** Request an out transfer, no checking of input parameters.
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[in] buffer Buffer with data to transfer.
- * @param[in] size Size of the buffer (in bytes).
- * @return Error code.
- */
-static int usb_pipe_write_no_check(usb_pipe_t *pipe, uint64_t setup,
-    const void *buffer, size_t size)
-{
-	/* Only interrupt and bulk transfers are supported */
-	if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
-	    pipe->transfer_type != USB_TRANSFER_BULK &&
-	    pipe->transfer_type != USB_TRANSFER_CONTROL)
-	    return ENOTSUP;
-
-	int ret = pipe_add_ref(pipe, false);
-	if (ret != EOK) {
-		return ret;
-	}
-
-	/* Ensure serialization over the phone. */
-	pipe_start_transaction(pipe);
-	async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
-	if (!exch) {
-		pipe_end_transaction(pipe);
-		pipe_drop_ref(pipe);
-		return ENOMEM;
-	}
-	ret = usbhc_write(exch, pipe->wire->address, pipe->endpoint_no,
-	    setup, buffer, size);
-	async_exchange_end(exch);
-	pipe_end_transaction(pipe);
-	pipe_drop_ref(pipe);
-	return ret;
-}
-
-/** Try to clear endpoint halt of default control pipe.
- *
- * @param pipe Pipe for control endpoint zero.
- */
-static void clear_self_endpoint_halt(usb_pipe_t *pipe)
-{
-	assert(pipe != NULL);
-
-	if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
-		return;
-	}
-
-
-	/* Prevent infinite recursion. */
-	pipe->auto_reset_halt = false;
-	usb_request_clear_endpoint_halt(pipe, 0);
-	pipe->auto_reset_halt = true;
-}
-
-/** Request a control read transfer on an endpoint pipe.
- *
- * This function encapsulates all three stages of a control transfer.
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[in] setup_buffer Buffer with the setup packet.
- * @param[in] setup_buffer_size Size of the setup packet (in bytes).
- * @param[out] data_buffer Buffer for incoming data.
- * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
- * @param[out] data_transfered_size Number of bytes that were actually
- *                                  transfered during the DATA stage.
- * @return Error code.
- */
-int usb_pipe_control_read(usb_pipe_t *pipe,
-    const void *setup_buffer, size_t setup_buffer_size,
-    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
-{
-	assert(pipe);
-
-	if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
-		return EINVAL;
-	}
-
-	if ((data_buffer == NULL) || (data_buffer_size == 0)) {
-		return EINVAL;
-	}
-
-	if ((pipe->direction != USB_DIRECTION_BOTH)
-	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
-		return EBADF;
-	}
-
-	uint64_t setup_packet;
-	memcpy(&setup_packet, setup_buffer, 8);
-
-	size_t act_size = 0;
-	const int rc = usb_pipe_read_no_check(pipe, setup_packet,
-	    data_buffer, data_buffer_size, &act_size);
-
-	if (rc == ESTALL) {
-		clear_self_endpoint_halt(pipe);
-	}
-
-	if (rc == EOK && data_transfered_size != NULL) {
-		*data_transfered_size = act_size;
-	}
-
-	return rc;
-}
-
-/** Request a control write transfer on an endpoint pipe.
- *
- * This function encapsulates all three stages of a control transfer.
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[in] setup_buffer Buffer with the setup packet.
- * @param[in] setup_buffer_size Size of the setup packet (in bytes).
- * @param[in] data_buffer Buffer with data to be sent.
- * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
- * @return Error code.
- */
-int usb_pipe_control_write(usb_pipe_t *pipe,
-    const void *setup_buffer, size_t setup_buffer_size,
-    const void *data_buffer, size_t data_buffer_size)
-{
-	assert(pipe);
-
-	if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
-		return EINVAL;
-	}
-
-	if ((data_buffer == NULL) && (data_buffer_size > 0)) {
-		return EINVAL;
-	}
-
-	if ((data_buffer != NULL) && (data_buffer_size == 0)) {
-		return EINVAL;
-	}
-
-	if ((pipe->direction != USB_DIRECTION_BOTH)
-	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
-		return EBADF;
-	}
-
-	uint64_t setup_packet;
-	memcpy(&setup_packet, setup_buffer, 8);
-
-	const int rc = usb_pipe_write_no_check(pipe, setup_packet,
-	    data_buffer, data_buffer_size);
-
-	if (rc == ESTALL) {
-		clear_self_endpoint_halt(pipe);
-	}
-
-	return rc;
-}
-
-/** Request a read (in) transfer on an endpoint pipe.
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[out] buffer Buffer where to store the data.
- * @param[in] size Size of the buffer (in bytes).
- * @param[out] size_transfered Number of bytes that were actually transfered.
- * @return Error code.
- */
-int usb_pipe_read(usb_pipe_t *pipe,
-    void *buffer, size_t size, size_t *size_transfered)
-{
-	assert(pipe);
-
-	if (buffer == NULL) {
-		return EINVAL;
-	}
-
-	if (size == 0) {
-		return EINVAL;
-	}
-
-	if (pipe->direction != USB_DIRECTION_IN) {
-		return EBADF;
-	}
-
-	if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
-		return EBADF;
-	}
-
-	size_t act_size = 0;
-	const int rc = usb_pipe_read_no_check(pipe, 0, buffer, size, &act_size);
-
-
-	if (rc == EOK && size_transfered != NULL) {
-		*size_transfered = act_size;
-	}
-
-	return rc;
-}
-
-/** Request a write (out) transfer on an endpoint pipe.
- *
- * @param[in] pipe Pipe used for the transfer.
- * @param[in] buffer Buffer with data to transfer.
- * @param[in] size Size of the buffer (in bytes).
- * @return Error code.
- */
-int usb_pipe_write(usb_pipe_t *pipe, const void *buffer, size_t size)
-{
-	assert(pipe);
-
-	if (buffer == NULL || size == 0) {
-		return EINVAL;
-	}
-
-	if (pipe->direction != USB_DIRECTION_OUT) {
-		return EBADF;
-	}
-
-	if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
-		return EBADF;
-	}
-
-	return usb_pipe_write_no_check(pipe, 0, buffer, size);
-}
-
-/**
- * @}
- */
Index: uspace/lib/usbdev/src/recognise.c
===================================================================
--- uspace/lib/usbdev/src/recognise.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbdev/src/recognise.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -45,9 +45,4 @@
 #include <errno.h>
 #include <assert.h>
-
-/** Index to append after device name for uniqueness. */
-static size_t device_name_index = 0;
-/** Mutex guard for device_name_index. */
-static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
 
 /** DDF operations of child devices. */
@@ -329,7 +324,8 @@
 	}
 
-	fibril_mutex_lock(&device_name_index_mutex);
-	const size_t this_device_name_index = device_name_index++;
-	fibril_mutex_unlock(&device_name_index_mutex);
+	/** Index to append after device name for uniqueness. */
+	static atomic_t device_name_index = {0};
+	const size_t this_device_name_index =
+	    (size_t) atomic_preinc(&device_name_index);
 
 	ddf_fun_t *child = NULL;
Index: uspace/lib/usbhost/include/usb/host/endpoint.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/endpoint.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbhost/include/usb/host/endpoint.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -95,9 +95,9 @@
 /** list_get_instance wrapper.
  * @param item Pointer to link member.
- * @return Pointer to enpoint_t structure.
+ * @return Pointer to endpoint_t structure.
  */
 static inline endpoint_t * endpoint_get_instance(link_t *item)
 {
-	return list_get_instance(item, endpoint_t, link);
+	return item ? list_get_instance(item, endpoint_t, link) : NULL;
 }
 #endif
Index: uspace/lib/usbhost/include/usb/host/usb_device_manager.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/usb_device_manager.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbhost/include/usb/host/usb_device_manager.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -59,5 +59,7 @@
 		devman_handle_t handle; /**< Devman handle of the device. */
 	} devices[USB_ADDRESS_COUNT];
+	/** Maximum speed allowed. */
 	usb_speed_t max_speed;
+	/** Protect access to members. */
 	fibril_mutex_t guard;
 	/** The last reserved address */
Index: uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -65,10 +65,17 @@
 	 */
 	size_t setup_size;
-	/** Actually used portion of the buffer */
-	size_t transfered_size;
-	/** Indicates success/failure of the communication */
-	int error;
 	/** Host controller function, passed to callback function */
 	ddf_fun_t *fun;
+
+	/** Actually used portion of the buffer
+	 * This member is never accessed by functions provided in this header,
+	 * with the exception of usb_transfer_batch_finish. For external use.
+	 */
+	size_t transfered_size;
+	/** Indicates success/failure of the communication
+	 * This member is never accessed by functions provided in this header,
+	 * with the exception of usb_transfer_batch_finish. For external use.
+	 */
+	int error;
 
 	/** Driver specific data */
@@ -106,20 +113,18 @@
 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance);
 
-void usb_transfer_batch_finish(const usb_transfer_batch_t *instance,
-    const void* data, size_t size);
+void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance,
+    const void* data, size_t size, int error);
 /*----------------------------------------------------------------------------*/
-/** Override error value and finishes transfer.
+/** Finish batch using stored error value and transferred size.
  *
  * @param[in] instance Batch structure to use.
  * @param[in] data Data to copy to the output buffer.
- * @param[in] size Size of @p data.
- * @param[in] error Set batch status to this error value.
  */
-static inline void usb_transfer_batch_finish_error(
-    usb_transfer_batch_t *instance, const void* data, size_t size, int error)
+static inline void usb_transfer_batch_finish(
+    const usb_transfer_batch_t *instance, const void* data)
 {
 	assert(instance);
-	instance->error = error;
-	usb_transfer_batch_finish(instance, data, size);
+	usb_transfer_batch_finish_error(
+	    instance, data, instance->transfered_size, instance->error);
 }
 /*----------------------------------------------------------------------------*/
Index: uspace/lib/usbhost/src/iface.c
===================================================================
--- uspace/lib/usbhost/src/iface.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbhost/src/iface.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -39,4 +39,14 @@
 #include <usb/host/hcd.h>
 
+/** Prepare generic usb_transfer_batch and schedule it.
+ * @param fun DDF fun
+ * @param target address and endpoint number.
+ * @param setup_data Data to use in setup stage (Control communication type)
+ * @param in Callback for device to host communication.
+ * @param out Callback for host to device communication.
+ * @param arg Callback parameter.
+ * @param name Communication identifier (for nicer output).
+ * @return Error code.
+ */
 static inline int send_batch(
     ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
@@ -89,4 +99,9 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Calls ep_add_hook upon endpoint registration.
+ * @param ep Endpoint to be registered.
+ * @param arg hcd_t in disguise.
+ * @return Error code.
+ */
 static int register_helper(endpoint_t *ep, void *arg)
 {
@@ -99,4 +114,8 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Calls ep_remove_hook upon endpoint removal.
+ * @param ep Endpoint to be unregistered.
+ * @param arg hcd_t in disguise.
+ */
 static void unregister_helper(endpoint_t *ep, void *arg)
 {
@@ -108,4 +127,8 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Calls ep_remove_hook upon endpoint removal. Prints warning.
+ * @param ep Endpoint to be unregistered.
+ * @param arg hcd_t in disguise.
+ */
 static void unregister_helper_warn(endpoint_t *ep, void *arg)
 {
@@ -119,9 +142,11 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Request address interface function
+/** Request address interface function.
  *
  * @param[in] fun DDF function that was called.
+ * @param[in] address Pointer to preferred USB address.
+ * @param[out] address Place to write a new address.
+ * @param[in] strict Fail if the preferred address is not available.
  * @param[in] speed Speed to associate with the new default address.
- * @param[out] address Place to write a new address.
  * @return Error code.
  */
@@ -140,5 +165,5 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Bind address interface function
+/** Bind address interface function.
  *
  * @param[in] fun DDF function that was called.
@@ -148,5 +173,5 @@
  */
 static int bind_address(
-  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
+    ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
 {
 	assert(fun);
@@ -176,5 +201,5 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Release address interface function
+/** Release address interface function.
  *
  * @param[in] fun DDF function that was called.
@@ -194,8 +219,18 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Register endpoint interface function.
+ * @param fun DDF function.
+ * @param address USB address of the device.
+ * @param endpoint USB endpoint number to be registered.
+ * @param transfer_type Endpoint's transfer type.
+ * @param direction USB communication direction the endpoint is capable of.
+ * @param max_packet_size Maximu size of packets the endpoint accepts.
+ * @param interval Preferred timeout between communication.
+ * @return Error code.
+ */
 static int register_endpoint(
     ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
     usb_transfer_type_t transfer_type, usb_direction_t direction,
-    size_t max_packet_size, unsigned int interval)
+    size_t max_packet_size, unsigned interval)
 {
 	assert(fun);
@@ -220,4 +255,11 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Unregister endpoint interface function.
+ * @param fun DDF function.
+ * @param address USB address of the endpoint.
+ * @param endpoint USB endpoint number.
+ * @param direction Communication direction of the enpdoint to unregister.
+ * @return Error code.
+ */
 static int unregister_endpoint(
     ddf_fun_t *fun, usb_address_t address,
@@ -233,4 +275,14 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Inbound communication interface function.
+ * @param fun DDF function.
+ * @param target Communication target.
+ * @param setup_data Data to use in setup stage (control transfers).
+ * @param data Pointer to data buffer.
+ * @param size Size of the data buffer.
+ * @param callback Function to call on communication end.
+ * @param arg Argument passed to the callback function.
+ * @return Error code.
+ */
 static int usb_read(ddf_fun_t *fun, usb_target_t target, uint64_t setup_data,
     uint8_t *data, size_t size, usbhc_iface_transfer_in_callback_t callback,
@@ -241,4 +293,14 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Outbound communication interface function.
+ * @param fun DDF function.
+ * @param target Communication target.
+ * @param setup_data Data to use in setup stage (control transfers).
+ * @param data Pointer to data buffer.
+ * @param size Size of the data buffer.
+ * @param callback Function to call on communication end.
+ * @param arg Argument passed to the callback function.
+ * @return Error code.
+ */
 static int usb_write(ddf_fun_t *fun, usb_target_t target, uint64_t setup_data,
     const uint8_t *data, size_t size,
@@ -249,4 +311,5 @@
 }
 /*----------------------------------------------------------------------------*/
+/** usbhc Interface implementation using hcd_t from libusbhost library. */
 usbhc_iface_t hcd_iface = {
 	.request_address = request_address,
Index: uspace/lib/usbhost/src/usb_device_manager.c
===================================================================
--- uspace/lib/usbhost/src/usb_device_manager.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbhost/src/usb_device_manager.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -26,5 +26,4 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup libusbhost
  * @{
@@ -41,5 +40,4 @@
  *
  * @param[in] instance Device manager structure to use.
- * @param[in] speed Speed of the device requiring address.
  * @return Free address, or error code.
  */
@@ -133,4 +131,5 @@
  * @param[in] handle Devman handle of the device.
  * @return Error code.
+ * @note Won't accept binding for default address.
  */
 int usb_device_manager_bind_address(usb_device_manager_t *instance,
@@ -184,5 +183,5 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Find USB address associated with the device
+/** Find USB address associated with the device.
  *
  * @param[in] instance Device manager structure to use.
@@ -208,5 +207,4 @@
 /*----------------------------------------------------------------------------*/
 /** Find devman handle and speed assigned to USB address.
- * Intentionally refuse to work on default address.
  *
  * @param[in] instance Device manager structure to use.
Index: uspace/lib/usbhost/src/usb_endpoint_manager.c
===================================================================
--- uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -26,4 +26,10 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+/**  @addtogroup libusbhost
+ * @{
+ */
+/** @file
+ * HC Endpoint management.
+ */
 
 #include <bool.h>
@@ -56,5 +62,5 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Get list that holds endpints for given address.
+/** Get list that holds endpoints for given address.
  * @param instance usb_endpoint_manager structure, non-null.
  * @param addr USB address, must be >= 0.
@@ -75,4 +81,5 @@
  * @return Pointer to endpoint_t structure representing given communication
  * target, NULL if there is no such endpoint registered.
+ * @note Assumes that the internal mutex is locked.
  */
 static endpoint_t * find_locked(usb_endpoint_manager_t *instance,
@@ -169,4 +176,5 @@
  *
  * Really ugly one. Resets toggle bit on all endpoints that need it.
+ * @TODO Use tools from libusbdev requests.h
  */
 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance,
@@ -184,4 +192,5 @@
 	case 0x01: /* Clear Feature -- resets only cleared ep */
 		/* Recipient is endpoint, value is zero (ENDPOINT_STALL) */
+		// TODO Use macros in libusbdev requests.h
 		if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
 			fibril_mutex_lock(&instance->guard);
@@ -202,5 +211,7 @@
 		/* Recipient must be device, this resets all endpoints,
 		 * In fact there should be no endpoints but EP 0 registered
-		 * as different interfaces use different endpoints. */
+		 * as different interfaces use different endpoints,
+		 * unless you're changing configuration or alternative
+		 * interface of an already setup device. */
 		if ((data[0] & 0xf) == 0) {
 			fibril_mutex_lock(&instance->guard);
@@ -385,4 +396,13 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Unregister and destroy all endpoints using given address.
+ * @param instance usb_endpoint_manager structure, non-null.
+ * @param address USB address.
+ * @param endpoint USB endpoint number.
+ * @param direction Communication direction.
+ * @param callback Function to call after unregister, before destruction.
+ * @arg Argument to pass to the callback function.
+ * @return Error code.
+ */
 void usb_endpoint_manager_remove_address(usb_endpoint_manager_t *instance,
     usb_address_t address, void (*callback)(endpoint_t *, void *), void *arg)
@@ -403,2 +423,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/src/usb_transfer_batch.c
===================================================================
--- uspace/lib/usbhost/src/usb_transfer_batch.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/lib/usbhost/src/usb_transfer_batch.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -33,5 +33,5 @@
  */
 #include <errno.h>
-#include <str_error.h>
+#include <macros.h>
 
 #include <usb/usb.h>
@@ -48,4 +48,5 @@
  * @param func_in callback on IN transfer completion.
  * @param func_out callback on OUT transfer completion.
+ * @param fun DDF function (passed to callback function).
  * @param arg Argument to pass to the callback function.
  * @param private_data driver specific per batch data.
@@ -121,7 +122,8 @@
  * @param[in] data Data to copy to the output buffer.
  * @param[in] size Size of @p data.
+ * @param[in] error Error value to use.
  */
-void usb_transfer_batch_finish(
-    const usb_transfer_batch_t *instance, const void *data, size_t size)
+void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance,
+    const void *data, size_t size, int error)
 {
 	assert(instance);
@@ -133,5 +135,5 @@
 		/* Check for commands that reset toggle bit */
 		if (instance->ep->transfer_type == USB_TRANSFER_CONTROL
-		    && instance->error == EOK) {
+		    && error == EOK) {
 			const usb_target_t target =
 			    {{ instance->ep->address, instance->ep->endpoint }};
@@ -139,17 +141,15 @@
 			    instance->setup_buffer);
 		}
-		instance->callback_out(instance->fun,
-		    instance->error, instance->arg);
+		instance->callback_out(instance->fun, error, instance->arg);
 	}
 
         if (instance->callback_in) {
 		/* We care about the data and there are some to copy */
+		const size_t safe_size = min(size, instance->buffer_size);
 		if (data) {
-			const size_t min_size = size < instance->buffer_size
-			    ? size : instance->buffer_size;
-	                memcpy(instance->buffer, data, min_size);
+	                memcpy(instance->buffer, data, safe_size);
 		}
-		instance->callback_in(instance->fun, instance->error,
-		    instance->transfered_size, instance->arg);
+		instance->callback_in(instance->fun, error,
+		    safe_size, instance->arg);
 	}
 }
Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -309,11 +309,9 @@
 	}
 
-	fs_va = as_get_mappable_page(comm_size);
-	if (fs_va == NULL) {
+	(void) async_share_out_finalize(callid, &fs_va);
+	if (fs_va == (void *) -1) {
 		async_answer_0(callid, EHANGUP);
 		return;
 	}
-
-	(void) async_share_out_finalize(callid, fs_va);
 
 	while (true) {
Index: uspace/srv/bd/file_bd/file_bd.c
===================================================================
--- uspace/srv/bd/file_bd/file_bd.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/bd/file_bd/file_bd.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -190,11 +190,9 @@
 	}
 
-	fs_va = as_get_mappable_page(comm_size);
-	if (fs_va == NULL) {
+	(void) async_share_out_finalize(callid, &fs_va);
+	if (fs_va == (void *) -1) {
 		async_answer_0(callid, EHANGUP);
 		return;
 	}
-
-	(void) async_share_out_finalize(callid, fs_va);
 
 	while (true) {
Index: uspace/srv/bd/gxe_bd/gxe_bd.c
===================================================================
--- uspace/srv/bd/gxe_bd/gxe_bd.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/bd/gxe_bd/gxe_bd.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -193,11 +193,9 @@
 	}
 
-	fs_va = as_get_mappable_page(comm_size);
-	if (fs_va == NULL) {
+	(void) async_share_out_finalize(callid, &fs_va);
+	if (fs_va == (void *) -1) {
 		async_answer_0(callid, EHANGUP);
 		return;
 	}
-
-	(void) async_share_out_finalize(callid, fs_va);
 
 	while (true) {
Index: uspace/srv/bd/part/guid_part/guid_part.c
===================================================================
--- uspace/srv/bd/part/guid_part/guid_part.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/bd/part/guid_part/guid_part.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -348,11 +348,9 @@
 	}
 
-	fs_va = as_get_mappable_page(comm_size);
-	if (fs_va == NULL) {
+	(void) async_share_out_finalize(callid, &fs_va);
+	if (fs_va == (void *) -1) {
 		async_answer_0(callid, EHANGUP);
 		return;
 	}
-
-	(void) async_share_out_finalize(callid, fs_va);
 
 	while (true) {
Index: uspace/srv/bd/part/mbr_part/mbr_part.c
===================================================================
--- uspace/srv/bd/part/mbr_part/mbr_part.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/bd/part/mbr_part/mbr_part.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -425,11 +425,9 @@
 	}
 
-	fs_va = as_get_mappable_page(comm_size);
-	if (fs_va == NULL) {
+	(void) async_share_out_finalize(callid, &fs_va);
+	if (fs_va == (void *) -1) {
 		async_answer_0(callid, EHANGUP);
 		return;
 	}
-
-	(void) async_share_out_finalize(callid, fs_va);
 
 	while (1) {
Index: uspace/srv/bd/rd/rd.c
===================================================================
--- uspace/srv/bd/rd/rd.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/bd/rd/rd.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -105,8 +105,6 @@
 	unsigned int flags;
 	if (async_share_out_receive(&callid, &comm_size, &flags)) {
-		fs_va = as_get_mappable_page(comm_size);
-		if (fs_va) {
-			(void) async_share_out_finalize(callid, fs_va);
-		} else {
+		(void) async_share_out_finalize(callid, &fs_va);
+		if (fs_va == (void *) -1) {
 			async_answer_0(callid, EHANGUP);
 			return;
@@ -224,11 +222,10 @@
 	
 	rd_size = ALIGN_UP(size, block_size);
-	rd_addr = as_get_mappable_page(rd_size);
-	
 	unsigned int flags =
 	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE;
-	ret = physmem_map((void *) addr_phys, rd_addr,
-	    ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
-	if (ret < 0) {
+	
+	ret = physmem_map((void *) addr_phys,
+	    ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags, &rd_addr);
+	if (ret != EOK) {
 		printf("%s: Error mapping RAM disk\n", NAME);
 		return false;
Index: uspace/srv/hid/fb/fb.c
===================================================================
--- uspace/srv/hid/fb/fb.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hid/fb/fb.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -304,7 +304,6 @@
 	}
 	
-	frontbuf->data = as_get_mappable_page(frontbuf->size);
-	int rc = async_answer_1(callid, EOK, (sysarg_t) frontbuf->data);
-	if (rc != EOK) {
+	int rc = async_share_out_finalize(callid, &frontbuf->data);
+	if ((rc != EOK) || (frontbuf->data == (void *) -1)) {
 		free(frontbuf);
 		async_answer_0(iid, ENOMEM);
@@ -348,7 +347,6 @@
 	}
 	
-	imagemap->data = as_get_mappable_page(imagemap->size);
-	int rc = async_answer_1(callid, EOK, (sysarg_t) imagemap->data);
-	if (rc != EOK) {
+	int rc = async_share_out_finalize(callid, &imagemap->data);
+	if ((rc != EOK) || (imagemap->data == (void *) -1)) {
 		free(imagemap);
 		async_answer_0(iid, ENOMEM);
Index: uspace/srv/hid/fb/port/ega.c
===================================================================
--- uspace/srv/hid/fb/port/ega.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hid/fb/port/ega.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -280,10 +280,8 @@
 	
 	ega.size = (width * height) << 1;
-	ega.addr = as_get_mappable_page(ega.size);
-	if (ega.addr == NULL)
-		return ENOMEM;
-	
-	rc = physmem_map((void *) paddr, ega.addr,
-	    ALIGN_UP(ega.size, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE);
+	
+	rc = physmem_map((void *) paddr,
+	    ALIGN_UP(ega.size, PAGE_SIZE) >> PAGE_WIDTH,
+	    AS_AREA_READ | AS_AREA_WRITE, (void *) &ega.addr);
 	if (rc != EOK)
 		return rc;
Index: uspace/srv/hid/fb/port/kchar.c
===================================================================
--- uspace/srv/hid/fb/port/kchar.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hid/fb/port/kchar.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -83,10 +83,7 @@
 		return rc;
 	
-	kchar.addr = as_get_mappable_page(1);
-	if (kchar.addr == NULL)
-		return ENOMEM;
-	
-	rc = physmem_map((void *) paddr, kchar.addr,
-	    ALIGN_UP(1, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE);
+	rc = physmem_map((void *) paddr,
+	    ALIGN_UP(1, PAGE_SIZE) >> PAGE_WIDTH,
+	    AS_AREA_READ | AS_AREA_WRITE, (void *) &kchar.addr);
 	if (rc != EOK)
 		return rc;
Index: uspace/srv/hid/fb/port/kfb.c
===================================================================
--- uspace/srv/hid/fb/port/kfb.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hid/fb/port/kfb.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -756,12 +756,8 @@
 	
 	kfb.size = scanline * height;
-	kfb.addr = as_get_mappable_page(kfb.size);
-	if (kfb.addr == NULL) {
-		free(kfb.glyphs);
-		return ENOMEM;
-	}
-	
-	rc = physmem_map((void *) paddr + offset, kfb.addr,
-	    ALIGN_UP(kfb.size, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE);
+	
+	rc = physmem_map((void *) paddr + offset,
+	    ALIGN_UP(kfb.size, PAGE_SIZE) >> PAGE_WIDTH,
+	    AS_AREA_READ | AS_AREA_WRITE, (void *) &kfb.addr);
 	if (rc != EOK) {
 		free(kfb.glyphs);
Index: uspace/srv/hid/fb/port/niagara.c
===================================================================
--- uspace/srv/hid/fb/port/niagara.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hid/fb/port/niagara.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -103,11 +103,6 @@
 		return rc;
 	
-	niagara.fifo =
-	    (output_fifo_t *) as_get_mappable_page(sizeof(output_fifo_t));
-	if (niagara.fifo == NULL)
-		return ENOMEM;
-	
-	rc = physmem_map((void *) paddr, (void *) niagara.fifo, 1,
-	    AS_AREA_READ | AS_AREA_WRITE);
+	rc = physmem_map((void *) paddr, 1,
+	    AS_AREA_READ | AS_AREA_WRITE, (void *) &niagara.fifo);
 	if (rc != EOK)
 		return rc;
Index: pace/srv/hid/input/include/sun.h
===================================================================
--- uspace/srv/hid/input/include/sun.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2009 Martin Decky
- * 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 kbdgen generic
- * @brief Sun keyboard virtual port driver.
- * @ingroup kbd
- * @{
- */
-/** @file
- */
-
-#ifndef KBD_SUN_H_
-#define KBD_SUN_H_
-
-extern int ns16550_port_init(void);
-extern int z8530_port_init(void);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/input/port/dummy.c
===================================================================
--- uspace/srv/hid/input/port/dummy.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ 	(revision )
@@ -1,59 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * 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 kbd_port
- * @brief	Dummy keyboard port driver.
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- */
-
-#include <kbd_port.h>
-#include <kbd.h>
-
-int kbd_port_init(void)
-{
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/** @}
-*/
Index: uspace/srv/hid/input/port/gxemul.c
===================================================================
--- uspace/srv/hid/input/port/gxemul.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hid/input/port/gxemul.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -90,5 +90,5 @@
 	async_set_interrupt_received(gxemul_irq_handler);
 	gxemul_cmds[0].addr = (void *) addr;
-	register_irq(inr, device_assign_devno(), 0, &gxemul_kbd);
+	irq_register(inr, device_assign_devno(), 0, &gxemul_kbd);
 	return 0;
 }
Index: uspace/srv/hid/input/port/msim.c
===================================================================
--- uspace/srv/hid/input/port/msim.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hid/input/port/msim.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -89,5 +89,5 @@
 	msim_cmds[0].addr = (void *) vaddr;
 	async_set_interrupt_received(msim_irq_handler);
-	register_irq(inr, device_assign_devno(), 0, &msim_kbd);
+	irq_register(inr, device_assign_devno(), 0, &msim_kbd);
 	
 	return 0;
Index: uspace/srv/hid/input/port/niagara.c
===================================================================
--- uspace/srv/hid/input/port/niagara.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hid/input/port/niagara.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -63,9 +63,4 @@
 #define POLL_INTERVAL  10000
 
-/**
- * Virtual address mapped to the buffer shared with the kernel counterpart.
- */
-static uintptr_t input_buffer_addr;
-
 /*
  * Kernel counterpart of the driver pushes characters (it has read) here.
@@ -102,8 +97,6 @@
 		return -1;
 	
-	input_buffer_addr = (uintptr_t) as_get_mappable_page(PAGE_SIZE);
-	int rc = physmem_map((void *) paddr, (void *) input_buffer_addr,
-	    1, AS_AREA_READ | AS_AREA_WRITE);
-	
+	int rc = physmem_map((void *) paddr, 1,
+	    AS_AREA_READ | AS_AREA_WRITE, (void *) &input_buffer);
 	if (rc != 0) {
 		printf("Niagara: uspace driver couldn't map physical memory: %d\n",
@@ -111,6 +104,4 @@
 		return rc;
 	}
-	
-	input_buffer = (input_buffer_t) input_buffer_addr;
 	
 	thread_id_t tid;
Index: uspace/srv/hid/input/port/ns16550.c
===================================================================
--- uspace/srv/hid/input/port/ns16550.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hid/input/port/ns16550.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -135,5 +135,5 @@
 	
 	async_set_interrupt_received(ns16550_irq_handler);
-	register_irq(inr, device_assign_devno(), inr, &ns16550_kbd);
+	irq_register(inr, device_assign_devno(), inr, &ns16550_kbd);
 	
 	return pio_enable((void *) ns16550_physical, 8, &vaddr);
Index: uspace/srv/hid/input/port/pl050.c
===================================================================
--- uspace/srv/hid/input/port/pl050.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hid/input/port/pl050.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -117,5 +117,5 @@
 	
 	async_set_interrupt_received(pl050_irq_handler);
-	register_irq(inr, device_assign_devno(), 0, &pl050_kbd);
+	irq_register(inr, device_assign_devno(), 0, &pl050_kbd);
 	
 	return 0;
Index: pace/srv/hid/input/port/sgcn.c
===================================================================
--- uspace/srv/hid/input/port/sgcn.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ 	(revision )
@@ -1,188 +1,0 @@
-/*
- * Copyright (c) 2008 Pavel Rimsky
- * 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 kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief SGCN (Serengeti Console) keyboard port driver.
- */
-
-#include <as.h>
-#include <ddi.h>
-#include <async.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sysinfo.h>
-#include <stdio.h>
-#include <thread.h>
-#include <bool.h>
-#include <errno.h>
-
-#define POLL_INTERVAL  10000
-
-/**
- * SGCN buffer header. It is placed at the very beginning of the SGCN
- * buffer.
- */
-typedef struct {
-	/** hard-wired to "CON" */
-	char magic[4];
-	
-	/** we don't need this */
-	char unused[8];
-	
-	/** offset within the SGCN buffer of the input buffer start */
-	uint32_t in_begin;
-	
-	/** offset within the SGCN buffer of the input buffer end */
-	uint32_t in_end;
-	
-	/** offset within the SGCN buffer of the input buffer read pointer */
-	uint32_t in_rdptr;
-	
-	/** offset within the SGCN buffer of the input buffer write pointer */
-	uint32_t in_wrptr;
-} __attribute__ ((packed)) sgcn_buffer_header_t;
-
-/*
- * Returns a pointer to the object of a given type which is placed at the given
- * offset from the console buffer beginning.
- */
-#define SGCN_BUFFER(type, offset) \
-		((type *) (sram_virt_addr + sram_buffer_offset + (offset)))
-
-/** Returns a pointer to the console buffer header. */
-#define SGCN_BUFFER_HEADER	(SGCN_BUFFER(sgcn_buffer_header_t, 0))
-
-/**
- * Virtual address mapped to SRAM.
- */
-static uintptr_t sram_virt_addr;
-
-/**
- * SGCN buffer offset within SGCN.
- */
-static uintptr_t sram_buffer_offset;
-
-/* polling thread */
-static void sgcn_thread_impl(void *arg);
-
-static volatile bool polling_disabled = false;
-
-/**
- * Initializes the SGCN driver.
- * Maps the physical memory (SRAM) and creates the polling thread. 
- */
-int kbd_port_init(void)
-{
-	sysarg_t sram_paddr;
-	if (sysinfo_get_value("sram.address.physical", &sram_paddr) != EOK)
-		return -1;
-	
-	sysarg_t sram_size;
-	if (sysinfo_get_value("sram.area.size", &sram_size) != EOK)
-		return -1;
-	
-	if (sysinfo_get_value("sram.buffer.offset", &sram_buffer_offset) != EOK)
-		sram_buffer_offset = 0;
-	
-	sram_virt_addr = (uintptr_t) as_get_mappable_page(sram_size);
-	
-	if (physmem_map((void *) sram_paddr, (void *) sram_virt_addr,
-	    sram_size / PAGE_SIZE, AS_AREA_READ | AS_AREA_WRITE) != 0) {
-		printf("SGCN: uspace driver could not map physical memory.");
-		return -1;
-	}
-	
-	thread_id_t tid;
-	int rc = thread_create(sgcn_thread_impl, NULL, "kbd_poll", &tid);
-	if (rc != 0)
-		return rc;
-	
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-	polling_disabled = true;
-}
-
-void kbd_port_reclaim(void)
-{
-	polling_disabled = false;
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/**
- * Handler of the "key pressed" event. Reads codes of all the pressed keys from
- * the buffer. 
- */
-static void sgcn_key_pressed(void)
-{
-	char c;
-	
-	uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
-	uint32_t end = SGCN_BUFFER_HEADER->in_end;
-	uint32_t size = end - begin;
-	
-	volatile char *buf_ptr = (volatile char *)
-		SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
-	volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
-	volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
-	
-	while (*in_rdptr_ptr != *in_wrptr_ptr) {
-		c = *buf_ptr;
-		*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
-		buf_ptr = (volatile char *)
-			SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
-		kbd_push_scancode(c);
-	}
-}
-
-/**
- * Thread to poll SGCN for keypresses.
- */
-static void sgcn_thread_impl(void *arg)
-{
-	(void) arg;
-
-	while (1) {
-		if (polling_disabled == false)
-			sgcn_key_pressed();
-		usleep(POLL_INTERVAL);
-	}
-}
-
-/** @}
- */
Index: pace/srv/hid/input/port/sun.c
===================================================================
--- uspace/srv/hid/input/port/sun.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ 	(revision )
@@ -1,89 +1,0 @@
-/*
- * Copyright (c) 2009 Martin Decky
- * 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 kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief Sun keyboard virtual port driver.
- */
-
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sun.h>
-#include <sysinfo.h>
-#include <errno.h>
-#include <bool.h>
-
-/** Sun keyboard virtual port driver.
- *
- * This is a virtual port driver which can use
- * both ns16550_port_init and z8530_port_init
- * according to the information passed from the
- * kernel. This is just a temporal hack.
- *
- */
-int kbd_port_init(void)
-{
-	sysarg_t z8530;
-	if (sysinfo_get_value("kbd.type.z8530", &z8530) != EOK)
-		z8530 = false;
-	
-	sysarg_t ns16550;
-	if (sysinfo_get_value("kbd.type.ns16550", &ns16550) != EOK)
-		ns16550 = false;
-	
-	if (z8530) {
-		if (z8530_port_init() == 0)
-			return 0;
-	}
-	
-	if (ns16550) {
-		if (ns16550_port_init() == 0)
-			return 0;
-	}
-	
-	return -1;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/** @}
-*/
Index: pace/srv/hid/input/port/z8530.c
===================================================================
--- uspace/srv/hid/input/port/z8530.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ 	(revision )
@@ -1,116 +1,0 @@
-/*
- * Copyright (c) 2006 Martin Decky
- * 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 kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief Z8530 keyboard port driver.
- */
-
-#include <ipc/irc.h>
-#include <async.h>
-#include <sysinfo.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sun.h>
-#include <sys/types.h>
-#include <ddi.h>
-#include <errno.h>
-
-#define CHAN_A_STATUS  4
-#define CHAN_A_DATA    6
-
-#define RR0_RCA  1
-
-static irq_cmd_t z8530_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,     /* Will be patched in run-time */
-		.dstarg = 1
-	},
-	{
-		.cmd = CMD_BTEST,
-		.value = RR0_RCA,
-		.srcarg = 1,
-		.dstarg = 3
-	},
-	{
-		.cmd = CMD_PREDICATE,
-		.value = 2,
-		.srcarg = 3
-	},
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,     /* Will be patched in run-time */
-		.dstarg = 2
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-	
-irq_code_t z8530_kbd = {
-	sizeof(z8530_cmds) / sizeof(irq_cmd_t),
-	z8530_cmds
-};
-
-static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-
-int z8530_port_init(void)
-{
-	sysarg_t kaddr;
-	if (sysinfo_get_value("kbd.address.kernel", &kaddr) != EOK)
-		return -1;
-	
-	sysarg_t inr;
-	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
-		return -1;
-	
-	z8530_cmds[0].addr = (void *) kaddr + CHAN_A_STATUS;
-	z8530_cmds[3].addr = (void *) kaddr + CHAN_A_DATA;
-	
-	async_set_interrupt_received(z8530_irq_handler);
-	register_irq(inr, device_assign_devno(), inr, &z8530_kbd);
-	
-	return 0;
-}
-
-static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(scan_code);
-	
-	if (irc_service)
-		async_msg_1(irc_phone, IRC_CLEAR_INTERRUPT,
-		    IPC_GET_IMETHOD(*call));
-}
-
-/** @}
- */
Index: uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c
===================================================================
--- uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -139,5 +139,5 @@
 
 	async_set_interrupt_received(s3c24xx_ts_irq_handler);
-	register_irq(inr, device_assign_devno(), 0, &ts_irq_code);
+	irq_register(inr, device_assign_devno(), 0, &ts_irq_code);
 
 	s3c24xx_ts_wait_for_int_mode(ts, updn_down);
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.c
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -275,5 +275,5 @@
 	cuda_irq_code.cmds[0].addr = (void *) &((cuda_t *) instance->cuda_kernel)->ifr;
 	async_set_interrupt_received(cuda_irq_handler);
-	register_irq(10, device_assign_devno(), 0, &cuda_irq_code);
+	irq_register(10, device_assign_devno(), 0, &cuda_irq_code);
 
 	/* Enable SR interrupt. */
Index: uspace/srv/hw/char/i8042/i8042.c
===================================================================
--- uspace/srv/hw/char/i8042/i8042.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hw/char/i8042/i8042.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -197,6 +197,6 @@
 	i8042_kbd.cmds[0].addr = (void *) &((i8042_t *) i8042_kernel)->status;
 	i8042_kbd.cmds[3].addr = (void *) &((i8042_t *) i8042_kernel)->data;
-	register_irq(inr_a, device_assign_devno(), 0, &i8042_kbd);
-	register_irq(inr_b, device_assign_devno(), 0, &i8042_kbd);
+	irq_register(inr_a, device_assign_devno(), 0, &i8042_kbd);
+	irq_register(inr_b, device_assign_devno(), 0, &i8042_kbd);
 	printf("%s: registered for interrupts %" PRIun " and %" PRIun "\n",
 	    NAME, inr_a, inr_b);
Index: uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c
===================================================================
--- uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -194,5 +194,5 @@
 	async_set_interrupt_received(s3c24xx_uart_irq_handler);
 
-	register_irq(inr, device_assign_devno(), 0, &uart_irq_code);
+	irq_register(inr, device_assign_devno(), 0, &uart_irq_code);
 
 	/* Enable FIFO, Tx trigger level: empty, Rx trigger level: 1 byte. */
Index: uspace/srv/hw/irc/obio/obio.c
===================================================================
--- uspace/srv/hw/irc/obio/obio.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/hw/irc/obio/obio.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -124,9 +124,9 @@
 	
 	base_phys = (void *) paddr;
-	base_virt = as_get_mappable_page(OBIO_SIZE);
 	
 	int flags = AS_AREA_READ | AS_AREA_WRITE;
-	int retval = physmem_map(base_phys, (void *) base_virt,
-	    ALIGN_UP(OBIO_SIZE, PAGE_SIZE) >> PAGE_WIDTH, flags);
+	int retval = physmem_map(base_phys,
+	    ALIGN_UP(OBIO_SIZE, PAGE_SIZE) >> PAGE_WIDTH, flags,
+	    (void *) &base_virt);
 	
 	if (retval < 0) {
Index: uspace/srv/net/tl/tcp/conn.c
===================================================================
--- uspace/srv/net/tl/tcp/conn.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/net/tl/tcp/conn.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -56,4 +56,5 @@
 
 LIST_INITIALIZE(conn_list);
+FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
 
 static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg);
@@ -61,9 +62,9 @@
 static void tcp_conn_tw_timer_clear(tcp_conn_t *conn);
 
-/** Create new segment structure.
+/** Create new connection structure.
  *
  * @param lsock		Local socket (will be deeply copied)
  * @param fsock		Foreign socket (will be deeply copied)
- * @return		New segment or NULL
+ * @return		New connection or NULL
  */
 tcp_conn_t *tcp_conn_new(tcp_sock_t *lsock, tcp_sock_t *fsock)
@@ -81,6 +82,10 @@
 		goto error;
 
+	fibril_mutex_initialize(&conn->lock);
+
+	/* One for the user, one for not being in closed state */
+	atomic_set(&conn->refcnt, 2);
+
 	/* Allocate receive buffer */
-	fibril_mutex_initialize(&conn->rcv_buf_lock);
 	fibril_condvar_initialize(&conn->rcv_buf_cv);
 	conn->rcv_buf_size = RCV_BUF_SIZE;
@@ -93,4 +98,5 @@
 
 	/** Allocate send buffer */
+	fibril_condvar_initialize(&conn->snd_buf_cv);
 	conn->snd_buf_size = SND_BUF_SIZE;
 	conn->snd_buf_used = 0;
@@ -113,9 +119,11 @@
 
 	/* Connection state change signalling */
-	fibril_mutex_initialize(&conn->cstate_lock);
 	fibril_condvar_initialize(&conn->cstate_cv);
+
+	conn->cstate_cb = NULL;
 
 	conn->cstate = st_listen;
 	conn->reset = false;
+	conn->deleted = false;
 	conn->ap = ap_passive;
 	conn->fin_is_acked = false;
@@ -141,4 +149,72 @@
 }
 
+/** Destroy connection structure.
+ *
+ * Connection structure should be destroyed when the folowing condtitions
+ * are met:
+ * (1) user has deleted the connection
+ * (2) the connection has entered closed state
+ * (3) nobody is holding references to the connection
+ *
+ * This happens when @a conn->refcnt is zero as we count (1) and (2)
+ * as special references.
+ *
+ * @param conn		Connection
+ */
+static void tcp_conn_free(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_free(%p)", conn->name, conn);
+	tcp_tqueue_fini(&conn->retransmit);
+
+	if (conn->rcv_buf != NULL)
+		free(conn->rcv_buf);
+	if (conn->snd_buf != NULL)
+		free(conn->snd_buf);
+	if (conn->tw_timer != NULL)
+		fibril_timer_destroy(conn->tw_timer);
+	free(conn);
+}
+
+/** Add reference to connection.
+ *
+ * Increase connection reference count by one.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_addref(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_addref(%p)", conn->name, conn);
+	atomic_inc(&conn->refcnt);
+}
+
+/** Remove reference from connection.
+ *
+ * Decrease connection reference count by one.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_delref(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_delref(%p)", conn->name, conn);
+
+	if (atomic_predec(&conn->refcnt) == 0)
+		tcp_conn_free(conn);
+}
+
+/** Delete connection.
+ *
+ * The caller promises not make no further references to @a conn.
+ * TCP will free @a conn eventually.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_delete(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_delete(%p)", conn->name, conn);
+
+	assert(conn->deleted == false);
+	tcp_conn_delref(conn);
+}
+
 /** Enlist connection.
  *
@@ -147,5 +223,8 @@
 void tcp_conn_add(tcp_conn_t *conn)
 {
+	tcp_conn_addref(conn);
+	fibril_mutex_lock(&conn_list_lock);
 	list_append(&conn->link, &conn_list);
+	fibril_mutex_unlock(&conn_list_lock);
 }
 
@@ -156,13 +235,33 @@
 void tcp_conn_remove(tcp_conn_t *conn)
 {
+	fibril_mutex_lock(&conn_list_lock);
 	list_remove(&conn->link);
+	fibril_mutex_unlock(&conn_list_lock);
+	tcp_conn_delref(conn);
 }
 
 static void tcp_conn_state_set(tcp_conn_t *conn, tcp_cstate_t nstate)
 {
-	fibril_mutex_lock(&conn->cstate_lock);
+	tcp_cstate_t old_state;
+
+	log_msg(LVL_DEBUG, "tcp_conn_state_set(%p)", conn);
+
+	old_state = conn->cstate;
 	conn->cstate = nstate;
 	fibril_condvar_broadcast(&conn->cstate_cv);
-	fibril_mutex_unlock(&conn->cstate_lock);
+
+	/* Run user callback function */
+	if (conn->cstate_cb != NULL) {
+		log_msg(LVL_DEBUG, "tcp_conn_state_set() - run user CB");
+		conn->cstate_cb(conn, conn->cstate_cb_arg);
+	} else {
+		log_msg(LVL_DEBUG, "tcp_conn_state_set() - no user CB");
+	}
+
+	assert(old_state != st_closed);
+	if (nstate == st_closed) {
+		/* Drop one reference for now being in closed state */
+		tcp_conn_delref(conn);
+	}
 }
 
@@ -251,11 +350,14 @@
  * A connection is uniquely identified by a socket pair. Look up our
  * connection map and return connection structure based on socket pair.
+ * The connection reference count is bumped by one.
  *
  * @param sp	Socket pair
  * @return	Connection structure or NULL if not found.
  */
-tcp_conn_t *tcp_conn_find(tcp_sockpair_t *sp)
+tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp)
 {
 	log_msg(LVL_DEBUG, "tcp_conn_find(%p)", sp);
+
+	fibril_mutex_lock(&conn_list_lock);
 
 	list_foreach(conn_list, link) {
@@ -266,8 +368,11 @@
 		    csp->local.addr.ipv4, csp->local.port);
 		if (tcp_sockpair_match(sp, csp)) {
+			tcp_conn_addref(conn);
+			fibril_mutex_unlock(&conn_list_lock);
 			return conn;
 		}
 	}
 
+	fibril_mutex_unlock(&conn_list_lock);
 	return NULL;
 }
@@ -287,4 +392,5 @@
 
 	fibril_condvar_broadcast(&conn->rcv_buf_cv);
+	fibril_condvar_broadcast(&conn->snd_buf_cv);
 }
 
@@ -397,6 +503,10 @@
 		    conn->snd_una, seg->ack, conn->snd_nxt);
 		if (!seq_no_ack_acceptable(conn, seg->ack)) {
-			log_msg(LVL_WARN, "ACK not acceptable, send RST.");
-			tcp_reply_rst(&conn->ident, seg);
+			if ((seg->ctrl & CTL_RST) == 0) {
+				log_msg(LVL_WARN, "ACK not acceptable, send RST");
+				tcp_reply_rst(&conn->ident, seg);
+			} else {
+				log_msg(LVL_WARN, "RST,ACK not acceptable, drop");
+			}
 			return;
 		}
@@ -404,10 +514,16 @@
 
 	if ((seg->ctrl & CTL_RST) != 0) {
-		log_msg(LVL_DEBUG, "%s: Connection reset. -> Closed",
-		    conn->name);
-		/* Reset connection */
-		tcp_conn_reset(conn);
-		/* XXX delete connection */
-		return;
+		/* If we get here, we have either an acceptable ACK or no ACK */
+		if ((seg->ctrl & CTL_ACK) != 0) {
+			log_msg(LVL_DEBUG, "%s: Connection reset. -> Closed",
+			    conn->name);
+			/* Reset connection */
+			tcp_conn_reset(conn);
+			return;
+		} else {
+			log_msg(LVL_DEBUG, "%s: RST without ACK, drop",
+			    conn->name);
+			return;
+		}
 	}
 
@@ -858,6 +974,4 @@
 	tcp_conn_trim_seg_to_wnd(conn, seg);
 
-	fibril_mutex_lock(&conn->rcv_buf_lock);
-
 	/* Determine how many bytes to copy */
 	text_size = tcp_segment_text_size(seg);
@@ -871,5 +985,4 @@
 	/* Signal to the receive function that new data has arrived */
 	fibril_condvar_broadcast(&conn->rcv_buf_cv);
-	fibril_mutex_unlock(&conn->rcv_buf_lock);
 
 	log_msg(LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
@@ -961,8 +1074,6 @@
 
 		/* Add FIN to the receive buffer */
-		fibril_mutex_lock(&conn->rcv_buf_lock);
 		conn->rcv_buf_fin = true;
 		fibril_condvar_broadcast(&conn->rcv_buf_cv);
-		fibril_mutex_unlock(&conn->rcv_buf_lock);
 
 		tcp_segment_delete(seg);
@@ -1073,6 +1184,10 @@
 	log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn);
 
+	fibril_mutex_lock(&conn->lock);
+
 	if (conn->cstate == st_closed) {
 		log_msg(LVL_DEBUG, "Connection already closed.");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
 		return;
 	}
@@ -1081,4 +1196,7 @@
 	tcp_conn_remove(conn);
 	tcp_conn_state_set(conn, st_closed);
+
+	fibril_mutex_unlock(&conn->lock);
+	tcp_conn_delref(conn);
 }
 
@@ -1089,4 +1207,5 @@
 void tcp_conn_tw_timer_set(tcp_conn_t *conn)
 {
+	tcp_conn_addref(conn);
 	fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func,
 	    (void *)conn);
@@ -1099,5 +1218,6 @@
 void tcp_conn_tw_timer_clear(tcp_conn_t *conn)
 {
-	fibril_timer_clear(conn->tw_timer);
+	if (fibril_timer_clear(conn->tw_timer) == fts_active)
+		tcp_conn_delref(conn);
 }
 
Index: uspace/srv/net/tl/tcp/conn.h
===================================================================
--- uspace/srv/net/tl/tcp/conn.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/net/tl/tcp/conn.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -40,4 +40,5 @@
 
 extern tcp_conn_t *tcp_conn_new(tcp_sock_t *, tcp_sock_t *);
+extern void tcp_conn_delete(tcp_conn_t *);
 extern void tcp_conn_add(tcp_conn_t *);
 extern void tcp_conn_remove(tcp_conn_t *);
@@ -45,5 +46,7 @@
 extern void tcp_conn_fin_sent(tcp_conn_t *);
 extern void tcp_conn_ack_of_fin_rcvd(tcp_conn_t *);
-extern tcp_conn_t *tcp_conn_find(tcp_sockpair_t *);
+extern tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *);
+extern void tcp_conn_addref(tcp_conn_t *);
+extern void tcp_conn_delref(tcp_conn_t *);
 extern bool tcp_conn_got_syn(tcp_conn_t *);
 extern void tcp_conn_segment_arrived(tcp_conn_t *, tcp_segment_t *);
Index: uspace/srv/net/tl/tcp/segment.c
===================================================================
--- uspace/srv/net/tl/tcp/segment.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/net/tl/tcp/segment.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -119,6 +119,12 @@
 		return NULL;
 
-	rseg->ctrl = CTL_RST;
-	rseg->seq = seg->ack;
+	if ((seg->ctrl & CTL_ACK) == 0) {
+		rseg->ctrl = CTL_RST | CTL_ACK;
+		rseg->seq = 0;
+		rseg->ack = seg->seq + seg->len;
+	} else {
+		rseg->ctrl = CTL_RST;
+		rseg->seq = seg->ack;
+	}
 
 	return rseg;
Index: uspace/srv/net/tl/tcp/sock.c
===================================================================
--- uspace/srv/net/tl/tcp/sock.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/net/tl/tcp/sock.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -52,4 +52,6 @@
 #define FRAGMENT_SIZE 1024
 
+#define MAX_BACKLOG 128
+
 /** Free ports pool start. */
 #define TCP_FREE_PORTS_START		1025
@@ -60,4 +62,6 @@
 static int last_used_port = TCP_FREE_PORTS_START - 1;
 static socket_ports_t gsock;
+
+static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg);
 
 void tcp_sock_init(void)
@@ -95,4 +99,5 @@
 {
 	tcp_sockdata_t *sock;
+	socket_core_t *sock_core;
 	int sock_id;
 	int rc;
@@ -106,6 +111,10 @@
 	}
 
+	fibril_mutex_initialize(&sock->lock);
 	sock->client = client;
 	sock->laddr.ipv4 = TCP_IPV4_ANY;
+	sock->lconn = NULL;
+	sock->backlog = 0;
+	list_initialize(&sock->ready);
 
 	sock_id = SOCKET_GET_SOCKET_ID(call);
@@ -115,4 +124,8 @@
 		return;
 	}
+
+	sock_core = socket_cores_find(&client->sockets, sock_id);
+	assert(sock_core != NULL);
+	sock->sock_core = sock_core;
 
 	refresh_answer(&answer, NULL);
@@ -167,4 +180,10 @@
 	socket_core_t *sock_core;
 	tcp_sockdata_t *socket;
+	tcp_error_t trc;
+	tcp_sock_t lsocket;
+	tcp_sock_t fsocket;
+	tcp_conn_t *conn;
+	tcp_sock_lconn_t *lconn;
+	int i;
 
 	log_msg(LVL_DEBUG, "tcp_sock_listen()");
@@ -177,4 +196,7 @@
 		return;
 	}
+
+	if (backlog > MAX_BACKLOG)
+		backlog = MAX_BACKLOG;
 
 	sock_core = socket_cores_find(&client->sockets, socket_id);
@@ -187,19 +209,55 @@
 
 	/*
-	 * XXX We do not do anything and defer action to accept().
-	 * This is a slight difference in semantics, but most servers
-	 * would just listen() and immediately accept() in a loop.
-	 *
-	 * The only difference is that there is a window between
-	 * listen() and accept() or two accept()s where we refuse
-	 * connections.
+	 * Prepare @c backlog listening connections.
 	 */
-	(void)backlog;
-	(void)socket;
-
+	fibril_mutex_lock(&socket->lock);
+
+	socket->backlog = backlog;
+	socket->lconn = calloc(sizeof(tcp_conn_t *), backlog);
+	if (socket->lconn == NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	log_msg(LVL_DEBUG, " - open connections");
+
+	lsocket.addr.ipv4 = TCP_IPV4_ANY;
+	lsocket.port = sock_core->port;
+	fsocket.addr.ipv4 = TCP_IPV4_ANY;
+	fsocket.port = TCP_PORT_ANY;
+
+	for (i = 0; i < backlog; i++) {
+
+		lconn = calloc(sizeof(tcp_sock_lconn_t), 1);
+		if (lconn == NULL) {
+			/* XXX Clean up */
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+
+		trc = tcp_uc_open(&lsocket, &fsocket, ap_passive,
+		    tcp_open_nonblock, &conn);
+		if (conn == NULL) {
+			/* XXX Clean up */
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+
+		tcp_uc_set_cstate_cb(conn, tcp_sock_cstate_cb, lconn);
+
+		assert(trc == TCP_EOK);
+		conn->name = (char *)"S";
+
+		lconn->conn = conn;
+		lconn->socket = socket;
+		link_initialize(&lconn->ready_list);
+		socket->lconn[i] = lconn;
+	}
+
+	fibril_mutex_unlock(&socket->lock);
 	async_answer_0(callid, EOK);
-	log_msg(LVL_DEBUG, "tcp_sock_listen(): notify data\n");
-	/* Push one accept notification to client's queue */
-	tcp_sock_notify_aconn(sock_core);
 }
 
@@ -248,4 +306,6 @@
 	}
 
+	fibril_mutex_lock(&socket->lock);
+
 	if (socket->laddr.ipv4 == TCP_IPV4_ANY) {
 		/* Find route to determine local IP address. */
@@ -254,4 +314,5 @@
 		    (void **)&phdr, &phdr_len);
 		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
 			async_answer_0(callid, rc);
 			log_msg(LVL_DEBUG, "tcp_transmit_connect: Failed to find route.");
@@ -269,8 +330,10 @@
 	fsocket.port = uint16_t_be2host(addr->sin_port);
 
-	trc = tcp_uc_open(&lsocket, &fsocket, ap_active, &socket->conn);
+	trc = tcp_uc_open(&lsocket, &fsocket, ap_active, 0, &socket->conn);
 
 	if (socket->conn != NULL)
 		socket->conn->name = (char *)"C";
+
+	fibril_mutex_unlock(&socket->lock);
 
 	switch (trc) {
@@ -305,4 +368,6 @@
 	tcp_sock_t fsocket;
 	tcp_conn_t *conn;
+	tcp_conn_t *rconn;
+	tcp_sock_lconn_t *lconn;
 	int rc;
 
@@ -319,12 +384,27 @@
 
 	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
 
 	log_msg(LVL_DEBUG, " - verify socket->conn");
 	if (socket->conn != NULL) {
+		fibril_mutex_unlock(&socket->lock);
 		async_answer_0(callid, EINVAL);
 		return;
 	}
 
-	log_msg(LVL_DEBUG, " - open connection");
+	if (list_empty(&socket->ready)) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+
+	lconn = list_get_instance(list_first(&socket->ready),
+	    tcp_sock_lconn_t, ready_list);
+	list_remove(&lconn->ready_list);
+
+	conn = lconn->conn;
+	tcp_uc_set_cstate_cb(conn, NULL, NULL);
+
+	/* Replenish listening connection */
 
 	lsocket.addr.ipv4 = TCP_IPV4_ANY;
@@ -333,34 +413,31 @@
 	fsocket.port = TCP_PORT_ANY;
 
-	trc = tcp_uc_open(&lsocket, &fsocket, ap_passive, &conn);
-	if (conn != NULL)
-		conn->name = (char *)"S";
-
-	log_msg(LVL_DEBUG, " - decode TCP return code");
-
-	switch (trc) {
-	case TCP_EOK:
-		rc = EOK;
-		break;
-	case TCP_ERESET:
-		rc = ECONNABORTED;
-		break;
-	default:
-		assert(false);
-	}
-
-	log_msg(LVL_DEBUG, " - check TCP return code");
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
+	trc = tcp_uc_open(&lsocket, &fsocket, ap_passive, tcp_open_nonblock,
+	    &rconn);
+	if (rconn == NULL) {
+		/* XXX Clean up */
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	tcp_uc_set_cstate_cb(rconn, tcp_sock_cstate_cb, lconn);
+
+	assert(trc == TCP_EOK);
+	rconn->name = (char *)"S";
+
+	lconn->conn = rconn;
+
+	/* Allocate socket for accepted connection */
 
 	log_msg(LVL_DEBUG, "tcp_sock_accept(): allocate asocket\n");
 	asocket = calloc(sizeof(tcp_sockdata_t), 1);
 	if (asocket == NULL) {
+		fibril_mutex_unlock(&socket->lock);
 		async_answer_0(callid, ENOMEM);
 		return;
 	}
 
+	fibril_mutex_initialize(&asocket->lock);
 	asocket->client = client;
 	asocket->conn = conn;
@@ -369,4 +446,5 @@
 	rc = socket_create(&client->sockets, client->sess, asocket, &asock_id);
 	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
 		async_answer_0(callid, rc);
 		return;
@@ -385,10 +463,8 @@
 	answer_call(callid, asock_core->socket_id, &answer, 3);
 
-	/* Push one accept notification to client's queue */
-	tcp_sock_notify_aconn(sock_core);
-
 	/* Push one fragment notification to client's queue */
+	log_msg(LVL_DEBUG, "tcp_sock_accept(): notify data\n");
 	tcp_sock_notify_data(asock_core);
-	log_msg(LVL_DEBUG, "tcp_sock_accept(): notify aconn\n");
+	fibril_mutex_unlock(&socket->lock);
 }
 
@@ -419,5 +495,8 @@
 
 	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
 	if (socket->conn == NULL) {
+		fibril_mutex_unlock(&socket->lock);
 		async_answer_0(callid, ENOTCONN);
 		return;
@@ -426,4 +505,5 @@
 	for (index = 0; index < fragments; index++) {
 		if (!async_data_write_receive(&wcallid, &length)) {
+			fibril_mutex_unlock(&socket->lock);
 			async_answer_0(callid, EINVAL);
 			return;
@@ -435,4 +515,5 @@
 		rc = async_data_write_finalize(wcallid, buffer, length);
 		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
 			async_answer_0(callid, rc);
 			return;
@@ -459,4 +540,5 @@
 
 		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
 			async_answer_0(callid, rc);
 			return;
@@ -467,4 +549,5 @@
 	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
 	answer_call(callid, EOK, &answer, 2);
+	fibril_mutex_unlock(&socket->lock);
 }
 
@@ -504,5 +587,8 @@
 
 	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
 	if (socket->conn == NULL) {
+		fibril_mutex_unlock(&socket->lock);
 		async_answer_0(callid, ENOTCONN);
 		return;
@@ -532,4 +618,5 @@
 	log_msg(LVL_DEBUG, "**** tcp_uc_receive -> %d", rc);
 	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
 		async_answer_0(callid, rc);
 		return;
@@ -545,4 +632,5 @@
 		log_msg(LVL_DEBUG, "addr read receive");
 		if (!async_data_read_receive(&rcallid, &addr_length)) {
+			fibril_mutex_unlock(&socket->lock);
 			async_answer_0(callid, EINVAL);
 			return;
@@ -555,4 +643,5 @@
 		rc = async_data_read_finalize(rcallid, &addr, addr_length);
 		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
 			async_answer_0(callid, EINVAL);
 			return;
@@ -562,4 +651,5 @@
 	log_msg(LVL_DEBUG, "data read receive");
 	if (!async_data_read_receive(&rcallid, &length)) {
+		fibril_mutex_unlock(&socket->lock);
 		async_answer_0(callid, EINVAL);
 		return;
@@ -580,4 +670,5 @@
 	/* Push one fragment notification to client's queue */
 	tcp_sock_notify_data(sock_core);
+	fibril_mutex_unlock(&socket->lock);
 }
 
@@ -603,23 +694,32 @@
 
 	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	rc = tcp_uc_close(socket->conn);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	/* Drain incoming data. This should really be done in the background. */
-	do {
-		trc = tcp_uc_receive(socket->conn, buffer, FRAGMENT_SIZE,
-		    &data_len, &xflags);
-	} while (trc == TCP_EOK);
+	fibril_mutex_lock(&socket->lock);
+
+	if (socket->conn != NULL) {
+		trc = tcp_uc_close(socket->conn);
+		if (trc != TCP_EOK && trc != TCP_ENOTEXIST) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EBADF);
+			return;
+		}
+
+		/* Drain incoming data. This should really be done in the background. */
+		do {
+			trc = tcp_uc_receive(socket->conn, buffer,
+			    FRAGMENT_SIZE, &data_len, &xflags);
+		} while (trc == TCP_EOK);
+
+		tcp_uc_delete(socket->conn);
+	}
 
 	rc = socket_destroy(net_sess, socket_id, &client->sockets, &gsock,
 	    tcp_free_sock_data);
 	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
 		async_answer_0(callid, rc);
 		return;
 	}
 
+	fibril_mutex_unlock(&socket->lock);
 	async_answer_0(callid, EOK);
 }
@@ -635,4 +735,31 @@
 	log_msg(LVL_DEBUG, "tcp_sock_setsockopt()");
 	async_answer_0(callid, ENOTSUP);
+}
+
+/** Called when connection state changes. */
+static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg)
+{
+	tcp_conn_status_t cstatus;
+	tcp_sock_lconn_t *lconn = (tcp_sock_lconn_t *)arg;
+	tcp_sockdata_t *socket = lconn->socket;
+
+	log_msg(LVL_DEBUG, "tcp_sock_cstate_cb()");
+	fibril_mutex_lock(&socket->lock);
+	assert(conn == lconn->conn);
+
+	tcp_uc_status(conn, &cstatus);
+	if (cstatus.cstate != st_established) {
+		fibril_mutex_unlock(&socket->lock);
+		return;
+	}
+
+	assert_link_not_used(&lconn->ready_list);
+	list_append(&lconn->ready_list, &socket->ready);
+
+	log_msg(LVL_DEBUG, "tcp_sock_cstate_cb(): notify accept");
+
+	/* Push one accept notification to client's queue */
+	tcp_sock_notify_aconn(socket->sock_core);
+	fibril_mutex_unlock(&socket->lock);
 }
 
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -36,4 +36,5 @@
 
 #include <async.h>
+#include <bitops.h>
 #include <byteorder.h>
 #include <errno.h>
@@ -191,11 +192,30 @@
 	tcp_pdu_t *pdu;
 	size_t hdr_size;
-
-	/* XXX Header options */
-	hdr_size = sizeof(tcp_header_t);
+	tcp_header_t *hdr;
+	uint32_t data_offset;
+
+	if (pdu_raw_size < sizeof(tcp_header_t)) {
+		log_msg(LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu",
+		    pdu_raw_size, sizeof(tcp_header_t));
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return EINVAL;
+	}
+
+	hdr = (tcp_header_t *)pdu_raw;
+	data_offset = BIT_RANGE_EXTRACT(uint32_t, DF_DATA_OFFSET_h, DF_DATA_OFFSET_l,
+	    uint16_t_be2host(hdr->doff_flags));
+
+	hdr_size = sizeof(uint32_t) * data_offset;
 
 	if (pdu_raw_size < hdr_size) {
 		log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
 		    pdu_raw_size, hdr_size);
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return EINVAL;
+	}
+
+	if (hdr_size < sizeof(tcp_header_t)) {
+		log_msg(LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu",
+		    hdr_size, sizeof(tcp_header_t));
 		pq_release_remote(net_sess, packet_get_id(packet));
 		return EINVAL;
Index: uspace/srv/net/tl/tcp/tcp_type.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_type.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/net/tl/tcp/tcp_type.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -152,7 +152,22 @@
 } acpass_t;
 
-typedef struct tcp_conn {
+typedef enum {
+	tcp_open_nonblock = 1
+} tcp_open_flags_t;
+
+typedef struct tcp_conn tcp_conn_t;
+
+/** Connection state change callback function */
+typedef void (*tcp_cstate_cb_t)(tcp_conn_t *, void *);
+
+/** Connection */
+struct tcp_conn {
 	char *name;
 	link_t link;
+
+	/** Connection state change callback function */
+	tcp_cstate_cb_t cstate_cb;
+	/** Argument to @c cstate_cb */
+	void *cstate_cb_arg;
 
 	/** Connection identification (local and foreign socket) */
@@ -161,4 +176,9 @@
 	/** Active or passive connection */
 	acpass_t ap;
+
+	/** Protects access to connection structure */
+	fibril_mutex_t lock;
+	/** Reference count */
+	atomic_t refcnt;
 
 	/** Connection state */
@@ -166,6 +186,6 @@
 	/** True if connection was reset */
 	bool reset;
-	/** Protects @c cstate */
-	fibril_mutex_t cstate_lock;
+	/** True if connection was deleted by user */
+	bool deleted;
 	/** Signalled when @c cstate changes */
 	fibril_condvar_t cstate_cv;
@@ -191,6 +211,4 @@
 	/** Receive buffer contains FIN */
 	bool rcv_buf_fin;
-	/** Receive buffer lock */
-	fibril_mutex_t rcv_buf_lock;
 	/** Receive buffer CV. Broadcast when new data is inserted */
 	fibril_condvar_t rcv_buf_cv;
@@ -204,4 +222,6 @@
 	/** Send buffer contains FIN */
 	bool snd_buf_fin;
+	/** Send buffer CV. Broadcast when space is made available in buffer */
+	fibril_condvar_t snd_buf_cv;
 
 	/** Send unacknowledged */
@@ -228,8 +248,10 @@
 	/** Initial receive sequence number */
 	uint32_t irs;
-} tcp_conn_t;
-
-typedef struct {
-	unsigned dummy;
+};
+
+/** Data returned by Status user call */
+typedef struct {
+	/** Connection state */
+	tcp_cstate_t cstate;
 } tcp_conn_status_t;
 
@@ -309,5 +331,9 @@
 } tcp_client_t;
 
-typedef struct {
+typedef struct tcp_sockdata {
+	/** Lock */
+	fibril_mutex_t lock;
+	/** Socket core */
+	socket_core_t *sock_core;
 	/** Client */
 	tcp_client_t *client;
@@ -316,5 +342,19 @@
 	/** Local address */
 	netaddr_t laddr;
+	/** Backlog size */
+	int backlog;
+	/** Array of listening connections, @c backlog elements */
+	struct tcp_sock_lconn **lconn;
+	/** List of connections (from lconn) that are ready to be accepted */
+	list_t ready;
 } tcp_sockdata_t;
+
+typedef struct tcp_sock_lconn {
+	tcp_conn_t *conn;
+	tcp_sockdata_t *socket;
+	int index;
+	link_t ready_list;
+} tcp_sock_lconn_t;
+
 
 #endif
Index: uspace/srv/net/tl/tcp/test.c
===================================================================
--- uspace/srv/net/tl/tcp/test.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/net/tl/tcp/test.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -62,5 +62,5 @@
 	fsock.addr.ipv4 = 0x7f000001;
 	printf("S: User open...\n");
-	tcp_uc_open(&lsock, &fsock, ap_passive, &conn);
+	tcp_uc_open(&lsock, &fsock, ap_passive, 0, &conn);
 	conn->name = (char *) "S";
 
@@ -102,5 +102,5 @@
 	async_usleep(1000*1000*3);
 	printf("C: User open...\n");
-	tcp_uc_open(&lsock, &fsock, ap_active, &conn);
+	tcp_uc_open(&lsock, &fsock, ap_active, 0, &conn);
 	conn->name = (char *) "C";
 
Index: uspace/srv/net/tl/tcp/tqueue.c
===================================================================
--- uspace/srv/net/tl/tcp/tqueue.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/net/tl/tcp/tqueue.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -188,5 +188,4 @@
 		/* We are sending out FIN */
 		ctrl = CTL_FIN;
-		tcp_conn_fin_sent(conn);
 	} else {
 		ctrl = 0;
@@ -206,4 +205,9 @@
 	if (send_fin)
 		conn->snd_buf_fin = false;
+
+	fibril_condvar_broadcast(&conn->snd_buf_cv);
+
+	if (send_fin)
+		tcp_conn_fin_sent(conn);
 
 	tcp_tqueue_seg(conn, seg);
@@ -313,6 +317,10 @@
 	log_msg(LVL_DEBUG, "### %s: retransmit_timeout_func(%p)", conn->name, conn);
 
+	fibril_mutex_lock(&conn->lock);
+
 	if (conn->cstate == st_closed) {
 		log_msg(LVL_DEBUG, "Connection already closed.");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
 		return;
 	}
@@ -321,4 +329,6 @@
 	if (link == NULL) {
 		log_msg(LVL_DEBUG, "Nothing to retransmit");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
 		return;
 	}
@@ -329,4 +339,6 @@
 	if (rt_seg == NULL) {
 		log_msg(LVL_ERROR, "Memory allocation failed.");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
 		/* XXX Handle properly */
 		return;
@@ -338,4 +350,7 @@
 	/* Reset retransmission timer */
 	tcp_tqueue_timer_set(tqe->conn);
+
+	fibril_mutex_unlock(&conn->lock);
+	tcp_conn_delref(conn);
 }
 
@@ -345,5 +360,8 @@
 	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_set()", conn->name);
 
-	(void) retransmit_timeout_func;
+	/* Clear first to make sure we update refcnt correctly */
+	tcp_tqueue_timer_clear(conn);
+
+	tcp_conn_addref(conn);
 	fibril_timer_set(conn->retransmit.timer, RETRANSMIT_TIMEOUT,
 	    retransmit_timeout_func, (void *) conn);
@@ -355,5 +373,6 @@
 	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_clear()", conn->name);
 
-	fibril_timer_clear(conn->retransmit.timer);
+	if (fibril_timer_clear(conn->retransmit.timer) == fts_active)
+		tcp_conn_delref(conn);
 }
 
Index: uspace/srv/net/tl/tcp/ucall.c
===================================================================
--- uspace/srv/net/tl/tcp/ucall.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/net/tl/tcp/ucall.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -53,4 +53,5 @@
  * @param fsock		Foreign socket
  * @param acpass	Active/passive
+ * @param oflags	Open flags
  * @param conn		Connection
  *
@@ -65,11 +66,11 @@
  */
 tcp_error_t tcp_uc_open(tcp_sock_t *lsock, tcp_sock_t *fsock, acpass_t acpass,
-    tcp_conn_t **conn)
+    tcp_open_flags_t oflags, tcp_conn_t **conn)
 {
 	tcp_conn_t *nconn;
 
-	log_msg(LVL_DEBUG, "tcp_uc_open(%p, %p, %s, %p)",
+	log_msg(LVL_DEBUG, "tcp_uc_open(%p, %p, %s, %s, %p)",
 	    lsock, fsock, acpass == ap_active ? "active" : "passive",
-	    conn);
+	    oflags == tcp_open_nonblock ? "nonblock" : "none", conn);
 
 	nconn = tcp_conn_new(lsock, fsock);
@@ -81,11 +82,16 @@
 	}
 
+	if (oflags == tcp_open_nonblock) {
+		*conn = nconn;
+		return TCP_EOK;
+	}
+
 	/* Wait for connection to be established or reset */
 	log_msg(LVL_DEBUG, "tcp_uc_open: Wait for connection.");
-	fibril_mutex_lock(&nconn->cstate_lock);
+	fibril_mutex_lock(&nconn->lock);
 	while (nconn->cstate == st_listen ||
 	    nconn->cstate == st_syn_sent ||
 	    nconn->cstate == st_syn_received) {
-		fibril_condvar_wait(&nconn->cstate_cv, &nconn->cstate_lock);
+		fibril_condvar_wait(&nconn->cstate_cv, &nconn->lock);
 	}
 
@@ -93,12 +99,13 @@
 		log_msg(LVL_DEBUG, "tcp_uc_open: Connection was reset.");
 		assert(nconn->cstate == st_closed);
-		fibril_mutex_unlock(&nconn->cstate_lock);
+		fibril_mutex_unlock(&nconn->lock);
 		return TCP_ERESET;
 	}
 
-	fibril_mutex_unlock(&nconn->cstate_lock);
+	fibril_mutex_unlock(&nconn->lock);
 	log_msg(LVL_DEBUG, "tcp_uc_open: Connection was established.");
 
 	*conn = nconn;
+	log_msg(LVL_DEBUG, "tcp_uc_open -> %p", nconn);
 	return TCP_EOK;
 }
@@ -113,6 +120,10 @@
 	log_msg(LVL_DEBUG, "%s: tcp_uc_send()", conn->name);
 
-	if (conn->cstate == st_closed)
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
 		return TCP_ENOTEXIST;
+	}
 
 	if (conn->cstate == st_listen) {
@@ -121,14 +132,23 @@
 	}
 
-	if (conn->snd_buf_fin)
+
+	if (conn->snd_buf_fin) {
+		fibril_mutex_unlock(&conn->lock);
 		return TCP_ECLOSING;
+	}
 
 	while (size > 0) {
 		buf_free = conn->snd_buf_size - conn->snd_buf_used;
-		while (buf_free == 0 && !conn->reset)
-			tcp_tqueue_new_data(conn);
-
-		if (conn->reset)
+		while (buf_free == 0 && !conn->reset) {
+			log_msg(LVL_DEBUG, "%s: buf_free == 0, waiting.",
+			    conn->name);
+			fibril_condvar_wait(&conn->snd_buf_cv, &conn->lock);
+			buf_free = conn->snd_buf_size - conn->snd_buf_used;
+		}
+
+		if (conn->reset) {
+			fibril_mutex_unlock(&conn->lock);
 			return TCP_ERESET;
+		}
 
 		xfer_size = min(size, buf_free);
@@ -139,7 +159,10 @@
 		conn->snd_buf_used += xfer_size;
 		size -= xfer_size;
+
+		tcp_tqueue_new_data(conn);
 	}
 
 	tcp_tqueue_new_data(conn);
+	fibril_mutex_unlock(&conn->lock);
 
 	return TCP_EOK;
@@ -154,18 +177,18 @@
 	log_msg(LVL_DEBUG, "%s: tcp_uc_receive()", conn->name);
 
-	if (conn->cstate == st_closed)
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
 		return TCP_ENOTEXIST;
-
-	fibril_mutex_lock(&conn->rcv_buf_lock);
+	}
 
 	/* Wait for data to become available */
 	while (conn->rcv_buf_used == 0 && !conn->rcv_buf_fin && !conn->reset) {
 		log_msg(LVL_DEBUG, "tcp_uc_receive() - wait for data");
-		fibril_condvar_wait(&conn->rcv_buf_cv, &conn->rcv_buf_lock);
+		fibril_condvar_wait(&conn->rcv_buf_cv, &conn->lock);
 	}
 
 	if (conn->rcv_buf_used == 0) {
-		fibril_mutex_unlock(&conn->rcv_buf_lock);
-
 		*rcvd = 0;
 		*xflags = 0;
@@ -173,8 +196,10 @@
 		if (conn->rcv_buf_fin) {
 			/* End of data, peer closed connection */
+			fibril_mutex_unlock(&conn->lock);
 			return TCP_ECLOSING;
 		} else {
 			/* Connection was reset */
 			assert(conn->reset);
+			fibril_mutex_unlock(&conn->lock);
 			return TCP_ERESET;
 		}
@@ -192,6 +217,4 @@
 	conn->rcv_wnd += xfer_size;
 
-	fibril_mutex_unlock(&conn->rcv_buf_lock);
-
 	/* TODO */
 	*xflags = 0;
@@ -203,4 +226,6 @@
 	    conn->name, xfer_size);
 
+	fibril_mutex_unlock(&conn->lock);
+
 	return TCP_EOK;
 }
@@ -211,13 +236,20 @@
 	log_msg(LVL_DEBUG, "%s: tcp_uc_close()", conn->name);
 
-	if (conn->cstate == st_closed)
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
 		return TCP_ENOTEXIST;
-
-	if (conn->snd_buf_fin)
+	}
+
+	if (conn->snd_buf_fin) {
+		fibril_mutex_unlock(&conn->lock);
 		return TCP_ECLOSING;
+	}
 
 	conn->snd_buf_fin = true;
 	tcp_tqueue_new_data(conn);
 
+	fibril_mutex_unlock(&conn->lock);
 	return TCP_EOK;
 }
@@ -233,6 +265,27 @@
 {
 	log_msg(LVL_DEBUG, "tcp_uc_status()");
-}
-
+	cstatus->cstate = conn->cstate;
+}
+
+/** Delete connection user call.
+ *
+ * (Not in spec.) Inform TCP that the user is done with this connection
+ * and will not make any further calls/references to it. TCP can deallocate
+ * the connection from now on.
+ */
+void tcp_uc_delete(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_delete()");
+	tcp_conn_delete(conn);
+}
+
+void tcp_uc_set_cstate_cb(tcp_conn_t *conn, tcp_cstate_cb_t cb, void *arg)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_set_ctate_cb(%p, %p, %p)",
+	    conn, cb, arg);
+
+	conn->cstate_cb = cb;
+	conn->cstate_cb_arg = arg;
+}
 
 /*
@@ -249,21 +302,32 @@
 	    sp->local.addr.ipv4, sp->local.port);
 
-	conn = tcp_conn_find(sp);
-	if (conn != NULL && conn->cstate != st_closed) {
-		if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY)
-			conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4;
-		if (conn->ident.foreign.port == TCP_PORT_ANY)
-			conn->ident.foreign.port = sp->foreign.port;
-		if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY)
-			conn->ident.local.addr.ipv4 = sp->local.addr.ipv4;
-
-		tcp_conn_segment_arrived(conn, seg);
-	} else {
-		if (conn == NULL)
-			log_msg(LVL_WARN, "No connection found.");
-		else
-			log_msg(LVL_WARN, "Connection is closed.");
+	conn = tcp_conn_find_ref(sp);
+	if (conn == NULL) {
+		log_msg(LVL_WARN, "No connection found.");
 		tcp_unexpected_segment(sp, seg);
-	}
+		return;
+	}
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		log_msg(LVL_WARN, "Connection is closed.");
+		tcp_unexpected_segment(sp, seg);
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY)
+		conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4;
+	if (conn->ident.foreign.port == TCP_PORT_ANY)
+		conn->ident.foreign.port = sp->foreign.port;
+	if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY)
+		conn->ident.local.addr.ipv4 = sp->local.addr.ipv4;
+
+	tcp_conn_segment_arrived(conn, seg);
+
+	fibril_mutex_unlock(&conn->lock);
+	tcp_conn_delref(conn);
 }
 
Index: uspace/srv/net/tl/tcp/ucall.h
===================================================================
--- uspace/srv/net/tl/tcp/ucall.h	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/net/tl/tcp/ucall.h	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -42,5 +42,6 @@
  * User calls
  */
-extern tcp_error_t tcp_uc_open(tcp_sock_t *, tcp_sock_t *, acpass_t, tcp_conn_t **);
+extern tcp_error_t tcp_uc_open(tcp_sock_t *, tcp_sock_t *, acpass_t,
+    tcp_open_flags_t, tcp_conn_t **);
 extern tcp_error_t tcp_uc_send(tcp_conn_t *, void *, size_t, xflags_t);
 extern tcp_error_t tcp_uc_receive(tcp_conn_t *, void *, size_t, size_t *, xflags_t *);
@@ -48,4 +49,6 @@
 extern void tcp_uc_abort(tcp_conn_t *);
 extern void tcp_uc_status(tcp_conn_t *, tcp_conn_status_t *);
+extern void tcp_uc_delete(tcp_conn_t *);
+extern void tcp_uc_set_cstate_cb(tcp_conn_t *, tcp_cstate_cb_t, void *);
 
 /*
Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision 22f05611fe61be707c3bee218be98f8f16f46f17)
+++ uspace/srv/vfs/vfs.c	(revision c520034c1c09f379852efaec5da361fb0a910b01)
@@ -172,12 +172,7 @@
 	 * Allocate and initialize the Path Lookup Buffer.
 	 */
-	plb = as_get_mappable_page(PLB_SIZE);
-	if (!plb) {
-		printf(NAME ": Cannot allocate a mappable piece of address space\n");
-		return ENOMEM;
-	}
-	
-	if (as_area_create(plb, PLB_SIZE, AS_AREA_READ | AS_AREA_WRITE |
-	    AS_AREA_CACHEABLE) != plb) {
+	plb = as_area_create((void *) -1, PLB_SIZE,
+	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
+	if (plb == (void *) -1) {
 		printf(NAME ": Cannot create address space area\n");
 		return ENOMEM;
