Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/Makefile	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -47,5 +47,4 @@
 	app/klog \
 	app/loc \
-	app/lsusb \
 	app/mkfat \
 	app/mkexfat \
@@ -85,4 +84,5 @@
 	srv/vfs \
 	srv/bd/ata_bd \
+	srv/bd/sata_bd \
 	srv/bd/file_bd \
 	srv/bd/gxe_bd \
@@ -105,4 +105,5 @@
 	drv/infrastructure/root \
 	drv/infrastructure/rootvirt \
+	drv/block/ahci \
 	drv/char/i8042 \
 	drv/char/ps2mouse \
@@ -169,4 +170,5 @@
 	DIRS += \
 		drv/infrastructure/rootmac \
+		drv/bus/pci/pciintel \
 		srv/hw/bus/cuda_adb
 endif
Index: uspace/app/bdsh/cmds/modules/cat/cat.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cat/cat.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/app/bdsh/cmds/modules/cat/cat.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -62,4 +62,5 @@
 static sysarg_t console_rows = 0;
 static bool should_quit = false;
+static bool dash_represents_stdin = false;
 
 static console_ctrl_t *console = NULL;
@@ -73,4 +74,5 @@
 	{ "more", no_argument, 0, 'm' },
 	{ "hex", no_argument, 0, 'x' },
+	{ "stdin", no_argument, 0, 's' },
 	{ 0, 0, 0, 0 }
 };
@@ -93,4 +95,5 @@
 		"  -m, --more       Pause after each screen full\n"
 		"  -x, --hex        Print bytes as hex values\n"
+		"  -s  --stdin      Treat `-' in file list as standard input\n"
 		"Currently, %s is under development, some options don't work.\n",
 		cmdname, cmdname);
@@ -172,5 +175,13 @@
 	off64_t file_size = 0, length = 0;
 
-	fd = open(fname, O_RDONLY);
+	bool reading_stdin = dash_represents_stdin && (str_cmp(fname, "-") == 0);
+	
+	if (reading_stdin) {
+		fd = fileno(stdin);
+		/* Allow storing the whole UTF-8 character. */
+		blen = STR_BOUNDS(1);
+	} else
+		fd = open(fname, O_RDONLY);
+	
 	if (fd < 0) {
 		printf("Unable to open %s\n", fname);
@@ -207,8 +218,17 @@
 
 	do {
-		bytes = read(fd, buff + copied_bytes, (
-			(length != CAT_FULL_FILE && length - (off64_t)count <= (off64_t)(blen - copied_bytes)) ?
-			(size_t)(length - count) :
-			(blen - copied_bytes) ) );
+		size_t bytes_to_read;
+		if (reading_stdin) {
+			bytes_to_read = 1;
+		} else {
+			if ((length != CAT_FULL_FILE) &&
+			    (length - (off64_t)count <= (off64_t)(blen - copied_bytes))) {
+				bytes_to_read = (size_t) (length - count);
+			} else {
+				bytes_to_read = blen - copied_bytes;
+			}
+		}
+		
+		bytes = read(fd, buff + copied_bytes, bytes_to_read);
 		bytes += copied_bytes;
 		copied_bytes = 0;
@@ -242,4 +262,7 @@
 			reads++;
 		}
+		
+		if (reading_stdin)
+			fflush(stdout);
 	} while (bytes > 0 && !should_quit && (count < length || length == CAT_FULL_FILE));
 
@@ -284,5 +307,5 @@
 
 	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
-		c = getopt_long(argc, argv, "xhvmH:t:b:", long_options, &opt_ind);
+		c = getopt_long(argc, argv, "xhvmH:t:b:s", long_options, &opt_ind);
 		switch (c) {
 		case 'h':
@@ -318,4 +341,7 @@
 			hex = true;
 			break;
+		case 's':
+			dash_represents_stdin = true;
+			break;
 		}
 	}
Index: uspace/app/lsusb/Makefile
===================================================================
--- uspace/app/lsusb/Makefile	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ 	(revision )
@@ -1,44 +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.
-#
-
-USPACE_PREFIX = ../..
-BINARY = lsusb
-
-LIBS = \
-	$(LIBUSBDEV_PREFIX)/libusbdev.a \
-	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS = \
-	-I$(LIBUSB_PREFIX)/include \
-	-I$(LIBUSBDEV_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
-
-SOURCES = \
-	main.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/lsusb/main.c
===================================================================
--- uspace/app/lsusb/main.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ 	(revision )
@@ -1,139 +1,0 @@
-/*
- * Copyright (c) 2010-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 lsusb
- * @{
- */
-/**
- * @file
- * Listing of USB host controllers.
- */
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <str_error.h>
-#include <bool.h>
-#include <getopt.h>
-#include <devman.h>
-#include <loc.h>
-#include <usb/dev/hub.h>
-#include <usb/hc.h>
-
-#define NAME "lsusb"
-
-#define MAX_USB_ADDRESS USB11_ADDRESS_MAX
-#define MAX_PATH_LENGTH 1024
-
-static void print_found_hc(service_id_t sid, const char *path)
-{
-	printf("Bus %" PRIun ": %s\n", sid, path);
-}
-static void print_found_dev(usb_address_t addr, const char *path)
-{
-	printf("  Device %02d: %s\n", addr, path);
-}
-
-static void print_hc_devices(devman_handle_t hc_handle)
-{
-	int rc;
-	usb_hc_connection_t conn;
-
-	usb_hc_connection_initialize(&conn, hc_handle);
-	rc = usb_hc_connection_open(&conn);
-	if (rc != EOK) {
-		printf(NAME ": failed to connect to HC: %s.\n",
-		    str_error(rc));
-		return;
-	}
-	usb_address_t addr;
-	for (addr = 1; addr < MAX_USB_ADDRESS; addr++) {
-		devman_handle_t dev_handle;
-		rc = usb_hc_get_handle_by_address(&conn, addr, &dev_handle);
-		if (rc != EOK) {
-			continue;
-		}
-		char path[MAX_PATH_LENGTH];
-		rc = devman_fun_get_path(dev_handle, path, MAX_PATH_LENGTH);
-		if (rc != EOK) {
-			continue;
-		}
-		print_found_dev(addr, path);
-	}
-	usb_hc_connection_close(&conn);
-}
-
-int main(int argc, char *argv[])
-{
-	category_id_t usbhc_cat;
-	service_id_t *svcs;
-	size_t count;
-	size_t i;
-	int rc;
-
-	rc = loc_category_get_id(USB_HC_CATEGORY, &usbhc_cat, 0);
-	if (rc != EOK) {
-		printf(NAME ": Error resolving category '%s'",
-		    USB_HC_CATEGORY);
-		return 1;
-	}
-
-	rc = loc_category_get_svcs(usbhc_cat, &svcs, &count);
-	if (rc != EOK) {
-		printf(NAME ": Error getting list of host controllers.\n");
-		return 1;
-	}
-
-	for (i = 0; i < count; i++) {
-		devman_handle_t hc_handle = 0;
-		int rc = usb_ddf_get_hc_handle_by_sid(svcs[i], &hc_handle);
-		if (rc != EOK) {
-			printf(NAME ": Error resolving handle of HC with SID %"
-			    PRIun ", skipping.\n", svcs[i]);
-			continue;
-		}
-		char path[MAX_PATH_LENGTH];
-		rc = devman_fun_get_path(hc_handle, path, MAX_PATH_LENGTH);
-		if (rc != EOK) {
-			printf(NAME ": Error resolving path of HC with SID %"
-			    PRIun ", skipping.\n", svcs[i]);
-			continue;
-		}
-		print_found_hc(svcs[i], path);
-		print_hc_devices(hc_handle);
-	}
-
-	free(svcs);
-
-	return 0;
-}
-
-
-/** @}
- */
Index: uspace/app/sportdmp/sportdmp.c
===================================================================
--- uspace/app/sportdmp/sportdmp.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/app/sportdmp/sportdmp.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -37,15 +37,25 @@
 static void syntax_print(void)
 {
-	fprintf(stderr, "Usage: sportdmp <baud> <device_service>\n");
+	fprintf(stderr, "Usage: sportdmp [--baud=<baud>] [device_service]\n");
 }
 
 int main(int argc, char **argv)
 {
-	const char* svc_path = "devices/\\hw\\pci0\\00:01.0\\com1\\a";
 	sysarg_t baud = 9600;
+	service_id_t svc_id;
 	
-	if (argc > 1) {
+	int arg = 1;
+	int rc;
+		
+	if (argc > arg && str_test_prefix(argv[arg], "--baud=")) {
+		size_t arg_offset = str_lsize(argv[arg], 7);
+		char* arg_str = argv[arg] + arg_offset;
+		if (str_length(arg_str) == 0) {
+			fprintf(stderr, "--baud requires an argument\n");
+			syntax_print();
+			return 1;
+		}
 		char *endptr;
-		baud = strtol(argv[1], &endptr, 10);
+		baud = strtol(arg_str, &endptr, 10);
 		if (*endptr != '\0') {
 			fprintf(stderr, "Invalid value for baud\n");
@@ -53,26 +63,55 @@
 			return 1;
 		}
+		arg++;
 	}
 	
-	if (argc > 2) {
-		svc_path = argv[2];
+	if (argc > arg) {
+		rc = loc_service_get_id(argv[arg], &svc_id, 0);
+		if (rc != EOK) {
+			fprintf(stderr, "Cannot find device service %s\n",
+			    argv[arg]);
+			return 1;
+		}
+		arg++;
+	}
+	else {
+		category_id_t serial_cat_id;
+		
+		rc = loc_category_get_id("serial", &serial_cat_id, 0);
+		if (rc != EOK) {
+			fprintf(stderr, "Failed getting id of category "
+			    "'serial'\n");
+			return 1;
+		}
+		
+		service_id_t *svc_ids;
+		size_t svc_count;
+		
+		rc = loc_category_get_svcs(serial_cat_id, &svc_ids, &svc_count);		if (rc != EOK) {
+			fprintf(stderr, "Failed getting list of services\n");
+			return 1;
+		}
+		
+		if (svc_count == 0) {
+			fprintf(stderr, "No service in category 'serial'\n");
+			free(svc_ids);
+			return 1;
+		}
+		
+		svc_id = svc_ids[0];
+		free(svc_ids);
 	}
 	
-	if (argc > 3) {
+	if (argc > arg) {
+		fprintf(stderr, "Too many arguments\n");
 		syntax_print();
 		return 1;
 	}
 	
-	service_id_t svc_id;
-	int rc = loc_service_get_id(svc_path, &svc_id, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		fprintf(stderr, "Cannot find device service %s\n", svc_path);
-		return 1;
-	}
 	
 	async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE, svc_id,
 	    IPC_FLAG_BLOCKING);
 	if (!sess) {
-		fprintf(stderr, "Failed connecting to service %s\n", svc_path);
+		fprintf(stderr, "Failed connecting to service\n");
 	}
 	
Index: uspace/app/usbinfo/Makefile
===================================================================
--- uspace/app/usbinfo/Makefile	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/app/usbinfo/Makefile	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -47,4 +47,5 @@
 	hid.c \
 	info.c \
+	list.c \
 	main.c
 
Index: uspace/app/usbinfo/list.c
===================================================================
--- uspace/app/usbinfo/list.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/app/usbinfo/list.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2010-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 lsusb
+ * @{
+ */
+/**
+ * @file
+ * Listing of USB host controllers.
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <str_error.h>
+#include <bool.h>
+#include <getopt.h>
+#include <devman.h>
+#include <loc.h>
+#include <usb/dev/hub.h>
+#include <usb/hc.h>
+
+#include "usbinfo.h"
+
+#define MAX_USB_ADDRESS USB11_ADDRESS_MAX
+#define MAX_PATH_LENGTH 1024
+
+static void print_found_hc(service_id_t sid, const char *path)
+{
+	printf("Bus %" PRIun ": %s\n", sid, path);
+}
+static void print_found_dev(usb_address_t addr, const char *path)
+{
+	printf("  Device %02d: %s\n", addr, path);
+}
+
+static void print_hc_devices(devman_handle_t hc_handle)
+{
+	int rc;
+	usb_hc_connection_t conn;
+
+	usb_hc_connection_initialize(&conn, hc_handle);
+	rc = usb_hc_connection_open(&conn);
+	if (rc != EOK) {
+		printf(NAME ": failed to connect to HC: %s.\n",
+		    str_error(rc));
+		return;
+	}
+	usb_address_t addr;
+	for (addr = 1; addr < MAX_USB_ADDRESS; addr++) {
+		devman_handle_t dev_handle;
+		rc = usb_hc_get_handle_by_address(&conn, addr, &dev_handle);
+		if (rc != EOK) {
+			continue;
+		}
+		char path[MAX_PATH_LENGTH];
+		rc = devman_fun_get_path(dev_handle, path, MAX_PATH_LENGTH);
+		if (rc != EOK) {
+			continue;
+		}
+		print_found_dev(addr, path);
+	}
+	usb_hc_connection_close(&conn);
+}
+
+void list(void)
+{
+	category_id_t usbhc_cat;
+	service_id_t *svcs;
+	size_t count;
+	size_t i;
+	int rc;
+
+	rc = loc_category_get_id(USB_HC_CATEGORY, &usbhc_cat, 0);
+	if (rc != EOK) {
+		printf(NAME ": Error resolving category '%s'",
+		    USB_HC_CATEGORY);
+		return;
+	}
+
+	rc = loc_category_get_svcs(usbhc_cat, &svcs, &count);
+	if (rc != EOK) {
+		printf(NAME ": Error getting list of host controllers.\n");
+		return;
+	}
+
+	for (i = 0; i < count; i++) {
+		devman_handle_t hc_handle = 0;
+		int rc = usb_ddf_get_hc_handle_by_sid(svcs[i], &hc_handle);
+		if (rc != EOK) {
+			printf(NAME ": Error resolving handle of HC with SID %"
+			    PRIun ", skipping.\n", svcs[i]);
+			continue;
+		}
+		char path[MAX_PATH_LENGTH];
+		rc = devman_fun_get_path(hc_handle, path, MAX_PATH_LENGTH);
+		if (rc != EOK) {
+			printf(NAME ": Error resolving path of HC with SID %"
+			    PRIun ", skipping.\n", svcs[i]);
+			continue;
+		}
+		print_found_hc(svcs[i], path);
+		print_hc_devices(hc_handle);
+	}
+
+	free(svcs);
+}
+
+
+/** @}
+ */
Index: uspace/app/usbinfo/main.c
===================================================================
--- uspace/app/usbinfo/main.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/app/usbinfo/main.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -62,4 +62,5 @@
 
 	_OPTION("-h --help", "Print this help and exit.");
+	_OPTION("-l --list", "Print a list of host controllers and devices.");
 	_OPTION("-i --identification", "Brief device identification.");
 	_OPTION("-m --match-ids", "Print match ids generated for the device.");
@@ -82,4 +83,5 @@
 	{"help", no_argument, NULL, 'h'},
 	{"identification", no_argument, NULL, 'i'},
+	{"list", no_argument, NULL, 'l'},
 	{"match-ids", no_argument, NULL, 'm'},
 	{"descriptor-tree", no_argument, NULL, 't'},
@@ -91,5 +93,5 @@
 	{0, 0, NULL, 0}
 };
-static const char *short_options = "himtTsSrR";
+static const char *short_options = "hilmtTsSrR";
 
 static usbinfo_action_t actions[] = {
@@ -146,4 +148,5 @@
 	}
 
+	bool something_active = false;
 	/*
 	 * Process command-line options. They determine what shall be
@@ -156,4 +159,7 @@
 		switch (opt) {
 			case -1:
+				break;
+			case 'l':
+				list();
 				break;
 			case '?':
@@ -168,4 +174,5 @@
 					if (actions[idx].opt == opt) {
 						actions[idx].active = true;
+						something_active = true;
 						break;
 					}
@@ -178,13 +185,4 @@
 
 	/* Set the default action. */
-	int idx = 0;
-	bool something_active = false;
-	while (actions[idx].opt != 0) {
-		if (actions[idx].active) {
-			something_active = true;
-			break;
-		}
-		idx++;
-	}
 	if (!something_active) {
 		actions[0].active = true;
Index: uspace/app/usbinfo/usbinfo.h
===================================================================
--- uspace/app/usbinfo/usbinfo.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/app/usbinfo/usbinfo.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -79,4 +79,5 @@
     dump_descriptor_in_tree_t, size_t, void *);
 
+void list(void);
 
 void dump_short_device_identification(usbinfo_device_t *);
Index: uspace/drv/block/ahci/Makefile
===================================================================
--- uspace/drv/block/ahci/Makefile	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/drv/block/ahci/Makefile	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2012 Petr Jerman
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = ahci
+
+SOURCES = \
+	ahci.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/block/ahci/ahci.c
===================================================================
--- uspace/drv/block/ahci/ahci.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/drv/block/ahci/ahci.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,1336 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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.
+ */
+
+/** @file
+ * AHCI SATA driver implementation.
+ */
+
+#include <as.h>
+#include <errno.h>
+#include <stdio.h>
+#include <devman.h>
+#include <ddf/interrupt.h>
+#include <ddf/log.h>
+#include <device/hw_res_parsed.h>
+#include <device/pci.h>
+#include <sysinfo.h>
+#include <ipc/irc.h>
+#include <ns.h>
+#include <ahci_iface.h>
+#include "ahci.h"
+#include "ahci_hw.h"
+#include "ahci_sata.h"
+
+#define NAME  "ahci"
+
+#define LO(ptr) \
+	((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) & 0xffffffff))
+
+#define HI(ptr) \
+	((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) >> 32))
+
+/** Interrupt pseudocode for a single port
+ *
+ * The interrupt handling works as follows:
+ *
+ * 1. Port interrupt status register is read
+ *    (stored as arg2).
+ * 2. If port interrupt is indicated, then:
+ *    3. Port interrupt status register is cleared.
+ *    4. Global interrupt status register is read
+ *       and cleared (any potential interrupts from
+ *       other ports are reasserted automatically).
+ *    5. Port number is stored as arg1.
+ *    6. The interrupt is accepted.
+ *
+ */
+#define AHCI_PORT_CMDS(port) \
+	{ \
+		/* Read port interrupt status register */ \
+		.cmd = CMD_PIO_READ_32, \
+		.addr = NULL, \
+		.dstarg = 2 \
+	}, \
+	{ \
+		/* Check if port asserted interrupt */ \
+		.cmd = CMD_PREDICATE, \
+		.value = 5, \
+		.srcarg = 2, \
+	}, \
+	{ \
+		/* Clear port interrupt status register */ \
+		.cmd = CMD_PIO_WRITE_A_32, \
+		.addr = NULL, \
+		.srcarg = 2 \
+	}, \
+	{ \
+		/* Read global interrupt status register */ \
+		.cmd = CMD_PIO_READ_32, \
+		.addr = NULL, \
+		.dstarg = 0 \
+	}, \
+	{ \
+		/* Clear global interrupt status register */ \
+		.cmd = CMD_PIO_WRITE_A_32, \
+		.addr = NULL, \
+		.srcarg = 0 \
+	}, \
+	{ \
+		/* Indicate port interrupt assertion */ \
+		.cmd = CMD_LOAD, \
+		.value = (port), \
+		.dstarg = 1 \
+	}, \
+	{ \
+		/* Accept the interrupt */ \
+		.cmd = CMD_ACCEPT \
+	}
+
+static int ahci_get_sata_device_name(ddf_fun_t *, size_t, char *);
+static int ahci_get_num_blocks(ddf_fun_t *, uint64_t *);
+static int ahci_get_block_size(ddf_fun_t *, size_t *);
+static int ahci_read_blocks(ddf_fun_t *, uint64_t, size_t, void *);
+static int ahci_write_blocks(ddf_fun_t *, uint64_t, size_t, void *);
+
+static int ahci_identify_device(sata_dev_t *);
+static int ahci_set_highest_ultra_dma_mode(sata_dev_t *);
+static int ahci_rb_fpdma(sata_dev_t *, void *, uint64_t);
+static int ahci_wb_fpdma(sata_dev_t *, void *, uint64_t);
+
+static void ahci_sata_devices_create(ahci_dev_t *, ddf_dev_t *);
+static ahci_dev_t *ahci_ahci_create(ddf_dev_t *);
+static void ahci_ahci_hw_start(ahci_dev_t *);
+
+static int ahci_dev_add(ddf_dev_t *);
+
+static void ahci_get_model_name(uint16_t *, char *);
+static int ahci_enable_interrupt(int);
+
+static fibril_mutex_t sata_devices_count_lock;
+static int sata_devices_count = 0;
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI Interface ----------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+static ahci_iface_t ahci_interface = {
+	.get_sata_device_name = &ahci_get_sata_device_name,
+	.get_num_blocks = &ahci_get_num_blocks,
+	.get_block_size = &ahci_get_block_size,
+	.read_blocks = &ahci_read_blocks,
+	.write_blocks = &ahci_write_blocks
+};
+
+static ddf_dev_ops_t ahci_ops = {
+	.interfaces[AHCI_DEV_IFACE] = &ahci_interface
+};
+
+static driver_ops_t driver_ops = {
+	.dev_add = &ahci_dev_add
+};
+
+static driver_t ahci_driver = {
+	.name = NAME,
+	.driver_ops = &driver_ops
+};
+
+/** Get SATA device name.
+ *
+ * @param fun                  Device function handling the call.
+ * @param sata_dev_name_length Length of the sata_dev_name buffer.
+ * @param sata_dev_name        Buffer for SATA device name.
+ *
+ * @return EOK.
+ *
+ */
+static int ahci_get_sata_device_name(ddf_fun_t *fun,
+    size_t sata_dev_name_length, char *sata_dev_name)
+{
+	sata_dev_t *sata = (sata_dev_t *) fun->driver_data;
+	str_cpy(sata_dev_name, sata_dev_name_length, sata->model);
+	return EOK;
+}
+
+/** Get Number of blocks in SATA device.
+ *
+ * @param fun    Device function handling the call.
+ * @param blocks Return number of blocks in SATA device.
+ *
+ * @return EOK.
+ *
+ */
+static int ahci_get_num_blocks(ddf_fun_t *fun, uint64_t *num_blocks)
+{
+	sata_dev_t *sata = (sata_dev_t *) fun->driver_data;
+	*num_blocks = sata->blocks;
+	return EOK;
+}
+
+/** Get SATA device block size.
+ *
+ * @param fun        Device function handling the call.
+ * @param block_size Return block size.
+ *
+ * @return EOK.
+ *
+ */
+static int ahci_get_block_size(ddf_fun_t *fun, size_t *block_size)
+{
+	sata_dev_t *sata = (sata_dev_t *) fun->driver_data;
+	*block_size = sata->block_size;
+	return EOK;
+}
+
+/** Read data blocks into SATA device.
+ *
+ * @param fun      Device function handling the call.
+ * @param blocknum Number of first block.
+ * @param count    Number of blocks to read.
+ * @param buf      Buffer for data.
+ *
+ * @return EOK if succeed, error code otherwise
+ *
+ */
+static int ahci_read_blocks(ddf_fun_t *fun, uint64_t blocknum,
+    size_t count, void *buf)
+{
+	sata_dev_t *sata = (sata_dev_t *) fun->driver_data;
+	
+	void *phys;
+	void *ibuf;
+	int rc = dmamem_map_anonymous(sata->block_size, AS_AREA_READ | AS_AREA_WRITE,
+	    0, &phys, (void **) &ibuf);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Cannot allocate read buffer.");
+		return rc;
+	}
+	
+	bzero(buf, sata->block_size);
+	
+	fibril_mutex_lock(&sata->lock);
+	
+	for (size_t cur = 0; cur < count; cur++) {
+		rc = ahci_rb_fpdma(sata, phys, blocknum + cur);
+		if (rc != EOK)
+			break;
+		
+		memcpy((void *) (((uint8_t *) buf) + (sata->block_size * cur)),
+		    ibuf, sata->block_size);
+	}
+	
+	fibril_mutex_unlock(&sata->lock);
+	dmamem_unmap_anonymous(ibuf);
+	
+	return rc;
+}
+
+/** Write data blocks into SATA device.
+ *
+ * @param fun      Device function handling the call.
+ * @param blocknum Number of first block.
+ * @param count    Number of blocks to write.
+ * @param buf      Buffer with data.
+ *
+ * @return EOK if succeed, error code otherwise
+ *
+ */
+static int ahci_write_blocks(ddf_fun_t *fun, uint64_t blocknum,
+    size_t count, void *buf)
+{
+	sata_dev_t *sata = (sata_dev_t *) fun->driver_data;
+	
+	void *phys;
+	void *ibuf;
+	int rc = dmamem_map_anonymous(sata->block_size, AS_AREA_READ | AS_AREA_WRITE,
+	    0, &phys, (void **) &ibuf);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Cannot allocate write buffer.");
+		return rc;
+	}
+	
+	fibril_mutex_lock(&sata->lock);
+	
+	for (size_t cur = 0; cur < count; cur++) {
+		memcpy(ibuf, (void *) (((uint8_t *) buf) + (sata->block_size * cur)),
+		    sata->block_size);
+		rc = ahci_wb_fpdma(sata, phys, blocknum + cur);
+		if (rc != EOK)
+			break;
+	}
+	
+	fibril_mutex_unlock(&sata->lock);
+	dmamem_unmap_anonymous(ibuf);
+	
+	return rc;
+}
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI Commands -----------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Wait for interrupt event.
+ *
+ * @param sata SATA device structure.
+ *
+ * @return Value of interrupt state register.
+ *
+ */
+static ahci_port_is_t ahci_wait_event(sata_dev_t *sata)
+{
+	fibril_mutex_lock(&sata->event_lock);
+	
+	sata->event_pxis = 0;
+	while (sata->event_pxis == 0)
+		fibril_condvar_wait(&sata->event_condvar, &sata->event_lock);
+	
+	ahci_port_is_t pxis = sata->event_pxis;
+	
+	if (ahci_port_is_permanent_error(pxis))
+		sata->is_invalid_device = true;
+	
+	fibril_mutex_unlock(&sata->event_lock);
+	
+	return pxis;
+}
+
+/** Set AHCI registers for identifying SATA device.
+ *
+ * @param sata SATA device structure.
+ * @param phys Physical address of working buffer.
+ *
+ */
+static void ahci_identify_device_cmd(sata_dev_t *sata, void *phys)
+{
+	volatile sata_std_command_frame_t *cmd =
+	    (sata_std_command_frame_t *) sata->cmd_table;
+	
+	cmd->fis_type = SATA_CMD_FIS_TYPE;
+	cmd->c = SATA_CMD_FIS_COMMAND_INDICATOR;
+	cmd->command = 0xec;
+	cmd->features = 0;
+	cmd->lba_lower = 0;
+	cmd->device = 0;
+	cmd->lba_upper = 0;
+	cmd->features_upper = 0;
+	cmd->count = 0;
+	cmd->reserved1 = 0;
+	cmd->control = 0;
+	cmd->reserved2 = 0;
+	
+	volatile ahci_cmd_prdt_t *prdt =
+	    (ahci_cmd_prdt_t *) (&sata->cmd_table[0x20]);
+	
+	prdt->data_address_low = LO(phys);
+	prdt->data_address_upper = HI(phys);
+	prdt->reserved1 = 0;
+	prdt->dbc = SATA_IDENTIFY_DEVICE_BUFFER_LENGTH - 1;
+	prdt->reserved2 = 0;
+	prdt->ioc = 0;
+	
+	sata->cmd_header->prdtl = 1;
+	sata->cmd_header->flags =
+	    AHCI_CMDHDR_FLAGS_CLEAR_BUSY_UPON_OK |
+	    AHCI_CMDHDR_FLAGS_2DWCMD;
+	sata->cmd_header->bytesprocessed = 0;
+	
+	/* Run command. */
+	sata->port->pxsact |= 1;
+	sata->port->pxci |= 1;
+}
+
+/** Set AHCI registers for identifying packet SATA device.
+ *
+ * @param sata SATA device structure.
+ * @param phys Physical address of working buffer.
+ *
+ */
+static void ahci_identify_packet_device_cmd(sata_dev_t *sata, void *phys)
+{
+	volatile sata_std_command_frame_t *cmd =
+	    (sata_std_command_frame_t *) sata->cmd_table;
+	
+	cmd->fis_type = SATA_CMD_FIS_TYPE;
+	cmd->c = SATA_CMD_FIS_COMMAND_INDICATOR;
+	cmd->command = 0xa1;
+	cmd->features = 0;
+	cmd->lba_lower = 0;
+	cmd->device = 0;
+	cmd->lba_upper = 0;
+	cmd->features_upper = 0;
+	cmd->count = 0;
+	cmd->reserved1 = 0;
+	cmd->control = 0;
+	cmd->reserved2 = 0;
+	
+	volatile ahci_cmd_prdt_t *prdt =
+	    (ahci_cmd_prdt_t *) (&sata->cmd_table[0x20]);
+	
+	prdt->data_address_low = LO(phys);
+	prdt->data_address_upper = HI(phys);
+	prdt->reserved1 = 0;
+	prdt->dbc = SATA_IDENTIFY_DEVICE_BUFFER_LENGTH - 1;
+	prdt->reserved2 = 0;
+	prdt->ioc = 0;
+	
+	sata->cmd_header->prdtl = 1;
+	sata->cmd_header->flags =
+	    AHCI_CMDHDR_FLAGS_CLEAR_BUSY_UPON_OK |
+	    AHCI_CMDHDR_FLAGS_2DWCMD;
+	sata->cmd_header->bytesprocessed = 0;
+	
+	/* Run command. */
+	sata->port->pxsact |= 1;
+	sata->port->pxci |= 1;
+}
+
+/** Fill device identification in SATA device structure.
+ *
+ * @param sata SATA device structure.
+ *
+ * @return EOK if succeed, error code otherwise.
+ *
+ */
+static int ahci_identify_device(sata_dev_t *sata)
+{
+	if (sata->is_invalid_device) {
+		ddf_msg(LVL_ERROR,
+		    "Identify command device on invalid device");
+		return EINTR;
+	}
+	
+	void *phys;
+	sata_identify_data_t *idata;
+	int rc = dmamem_map_anonymous(SATA_IDENTIFY_DEVICE_BUFFER_LENGTH,
+	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, (void **) &idata);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Cannot allocate buffer to identify device.");
+		return rc;
+	}
+	
+	bzero(idata, SATA_IDENTIFY_DEVICE_BUFFER_LENGTH);
+	
+	fibril_mutex_lock(&sata->lock);
+	
+	ahci_identify_device_cmd(sata, phys);
+	ahci_port_is_t pxis = ahci_wait_event(sata);
+	
+	if (sata->is_invalid_device) {
+		ddf_msg(LVL_ERROR,
+		    "Unrecoverable error during ata identify device");
+		goto error;
+	}
+	
+	if (ahci_port_is_tfes(pxis)) {
+		ahci_identify_packet_device_cmd(sata, phys);
+		pxis = ahci_wait_event(sata);
+		
+		if ((sata->is_invalid_device) || (ahci_port_is_error(pxis))) {
+			ddf_msg(LVL_ERROR,
+			    "Unrecoverable error during ata identify packet device");
+			goto error;
+		}
+		
+		sata->is_packet_device = true;
+	}
+	
+	ahci_get_model_name(idata->model_name, sata->model);
+	
+	/*
+	 * Due to QEMU limitation (as of 2012-06-22),
+	 * only NCQ FPDMA mode is supported.
+	 */
+	if ((idata->sata_cap & sata_np_cap_ncq) == 0) {
+		ddf_msg(LVL_ERROR, "%s: NCQ must be supported", sata->model);
+		goto error;
+	}
+	
+	uint16_t logsec = idata->physical_logic_sector_size;
+	if ((logsec & 0xc000) == 0x4000) {
+		/* Length of sector may be larger than 512 B */
+		if (logsec & 0x0100) {
+			/* Size of sector is larger than 512 B */
+			ddf_msg(LVL_ERROR,
+			    "%s: Sector length other than 512 B not supported",
+			    sata->model);
+			goto error;
+		}
+		
+		if ((logsec & 0x0200) && ((logsec & 0x000f) != 0)) {
+			/* Physical sectors per logical sector is greather than 1 */
+			ddf_msg(LVL_ERROR,
+			    "%s: Sector length other than 512 B not supported",
+			    sata->model);
+			goto error;
+		}
+	}
+	
+	if (sata->is_packet_device) {
+		/*
+		 * Due to QEMU limitation (as of 2012-06-22),
+		 * only NCQ FPDMA mode supported - block size is
+		 * 512 B, not 2048 B!
+		 */
+		sata->block_size = SATA_DEFAULT_SECTOR_SIZE;
+		sata->blocks = 0;
+	} else {
+		sata->block_size = SATA_DEFAULT_SECTOR_SIZE;
+		
+		if ((idata->caps & sata_rd_cap_lba) == 0) {
+			ddf_msg(LVL_ERROR, "%s: LBA for NCQ must be supported",
+			    sata->model);
+			goto error;
+		} else if ((idata->cmd_set1 & sata_cs1_addr48) == 0) {
+			sata->blocks = (uint32_t) idata->total_lba28_0 |
+			    ((uint32_t) idata->total_lba28_1 << 16);
+		} else {
+			/* Device supports LBA-48 addressing. */
+			sata->blocks = (uint64_t) idata->total_lba48_0 |
+			    ((uint64_t) idata->total_lba48_1 << 16) |
+			    ((uint64_t) idata->total_lba48_2 << 32) |
+			    ((uint64_t) idata->total_lba48_3 << 48);
+		}
+	}
+	
+	uint8_t udma_mask = idata->udma & 0x007f;
+	sata->highest_udma_mode = (uint8_t) -1;
+	if (udma_mask == 0) {
+		ddf_msg(LVL_ERROR,
+		    "%s: UDMA mode for NCQ FPDMA mode must be supported",
+		    sata->model);
+		goto error;
+	} else {
+		for (uint8_t i = 0; i < 7; i++) {
+			if (udma_mask & (1 << i))
+				sata->highest_udma_mode = i;
+		}
+	}
+	
+	fibril_mutex_unlock(&sata->lock);
+	dmamem_unmap_anonymous(idata);
+	
+	return EOK;
+	
+error:
+	fibril_mutex_unlock(&sata->lock);
+	dmamem_unmap_anonymous(idata);
+	
+	return EINTR;
+}
+
+/** Set AHCI registers for setting SATA device transfer mode.
+ *
+ * @param sata SATA device structure.
+ * @param phys Physical address of working buffer.
+ * @param mode Required mode.
+ *
+ */
+static void ahci_set_mode_cmd(sata_dev_t *sata, void* phys, uint8_t mode)
+{
+	volatile sata_std_command_frame_t *cmd =
+	    (sata_std_command_frame_t *) sata->cmd_table;
+	
+	cmd->fis_type = SATA_CMD_FIS_TYPE;
+	cmd->c = SATA_CMD_FIS_COMMAND_INDICATOR; 
+	cmd->command = 0xef;
+	cmd->features = 0x03;
+	cmd->lba_lower = 0;
+	cmd->device = 0;
+	cmd->lba_upper = 0;
+	cmd->features_upper = 0;
+	cmd->count = mode;
+	cmd->reserved1 = 0;
+	cmd->control = 0;
+	cmd->reserved2 = 0;
+	
+	volatile ahci_cmd_prdt_t *prdt =
+	    (ahci_cmd_prdt_t *) (&sata->cmd_table[0x20]);
+	
+	prdt->data_address_low = LO(phys);
+	prdt->data_address_upper = HI(phys);
+	prdt->reserved1 = 0;
+	prdt->dbc = SATA_SET_FEATURE_BUFFER_LENGTH - 1;
+	prdt->reserved2 = 0;
+	prdt->ioc = 0;
+	
+	sata->cmd_header->prdtl = 1;
+	sata->cmd_header->flags =
+	    AHCI_CMDHDR_FLAGS_CLEAR_BUSY_UPON_OK |
+	    AHCI_CMDHDR_FLAGS_2DWCMD;
+	sata->cmd_header->bytesprocessed = 0;
+	
+	/* Run command. */
+	sata->port->pxsact |= 1;
+	sata->port->pxci |= 1;
+}
+
+/** Set highest ultra DMA mode supported by SATA device.
+ *
+ * @param sata SATA device structure.
+ *
+ * @return EOK if succeed, error code otherwise
+ *
+ */
+static int ahci_set_highest_ultra_dma_mode(sata_dev_t *sata)
+{
+	if (sata->is_invalid_device) {
+		ddf_msg(LVL_ERROR,
+		    "%s: Setting highest UDMA mode on invalid device",
+		    sata->model);
+		return EINTR;
+	}
+	
+	if (sata->highest_udma_mode == (uint8_t) -1) {
+		ddf_msg(LVL_ERROR,
+		    "%s: No AHCI UDMA support.", sata->model);
+		return EINTR;
+	}
+	
+	if (sata->highest_udma_mode > 6) {
+		ddf_msg(LVL_ERROR,
+		    "%s: Unknown AHCI UDMA mode.", sata->model);
+		return EINTR;
+	}
+	
+	void *phys;
+	sata_identify_data_t *idata;
+	int rc = dmamem_map_anonymous(SATA_SET_FEATURE_BUFFER_LENGTH,
+	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, (void **) &idata);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Cannot allocate buffer for device set mode.");
+		return rc;
+	}
+	
+	bzero(idata, SATA_SET_FEATURE_BUFFER_LENGTH);
+	
+	fibril_mutex_lock(&sata->lock);
+	
+	uint8_t mode = 0x40 | (sata->highest_udma_mode & 0x07);
+	ahci_set_mode_cmd(sata, phys, mode);
+	ahci_port_is_t pxis = ahci_wait_event(sata);
+	
+	if (sata->is_invalid_device) {
+		ddf_msg(LVL_ERROR,
+		    "%s: Unrecoverable error during set highest UDMA mode",
+		    sata->model);
+		goto error;
+	}
+	
+	if (ahci_port_is_error(pxis)) {
+		ddf_msg(LVL_ERROR,
+		    "%s: Error during set highest UDMA mode", sata->model);
+		goto error;
+	}
+	
+	fibril_mutex_unlock(&sata->lock);
+	dmamem_unmap_anonymous(idata);
+	
+	return EOK;
+	
+error:
+	fibril_mutex_unlock(&sata->lock);
+	dmamem_unmap_anonymous(idata);
+	
+	return EINTR;
+}
+
+/** Set AHCI registers for reading one sector from the SATA device using FPDMA.
+ *
+ * @param sata     SATA device structure.
+ * @param phys     Physical address of buffer for sector data.
+ * @param blocknum Block number to read.
+ *
+ */
+static void ahci_rb_fpdma_cmd(sata_dev_t *sata, void *phys, uint64_t blocknum)
+{
+	volatile sata_ncq_command_frame_t *cmd =
+	    (sata_ncq_command_frame_t *) sata->cmd_table;
+	
+	cmd->fis_type = SATA_CMD_FIS_TYPE;
+	cmd->c = SATA_CMD_FIS_COMMAND_INDICATOR;
+	cmd->command = 0x60;
+	cmd->tag = 0;
+	cmd->control = 0;
+	
+	cmd->reserved1 = 0;
+	cmd->reserved2 = 0;
+	cmd->reserved3 = 0;
+	cmd->reserved4 = 0;
+	cmd->reserved5 = 0;
+	cmd->reserved6 = 0;
+	
+	cmd->sector_count_low = 1;
+	cmd->sector_count_high = 0;
+	
+	cmd->lba0 = blocknum & 0xff;
+	cmd->lba1 = (blocknum >> 8) & 0xff;
+	cmd->lba2 = (blocknum >> 16) & 0xff;
+	cmd->lba3 = (blocknum >> 24) & 0xff;
+	cmd->lba4 = (blocknum >> 32) & 0xff;
+	cmd->lba5 = (blocknum >> 40) & 0xff;
+	
+	volatile ahci_cmd_prdt_t *prdt =
+	    (ahci_cmd_prdt_t *) (&sata->cmd_table[0x20]);
+	
+	prdt->data_address_low = LO(phys);
+	prdt->data_address_upper = HI(phys);
+	prdt->reserved1 = 0;
+	prdt->dbc = sata->block_size - 1;
+	prdt->reserved2 = 0;
+	prdt->ioc = 0;
+	
+	sata->cmd_header->prdtl = 1;
+	sata->cmd_header->flags =
+	    AHCI_CMDHDR_FLAGS_CLEAR_BUSY_UPON_OK |
+	    AHCI_CMDHDR_FLAGS_5DWCMD;
+	sata->cmd_header->bytesprocessed = 0;
+	
+	sata->port->pxsact |= 1;
+	sata->port->pxci |= 1;
+}
+
+/** Read one sector from the SATA device using FPDMA.
+ *
+ * @param sata     SATA device structure.
+ * @param phys     Physical address of buffer for sector data.
+ * @param blocknum Block number to read.
+ *
+ * @return EOK if succeed, error code otherwise
+ *
+ */
+static int ahci_rb_fpdma(sata_dev_t *sata, void *phys, uint64_t blocknum)
+{
+	if (sata->is_invalid_device) {
+		ddf_msg(LVL_ERROR,
+		    "%s: FPDMA read from invalid device", sata->model);
+		return EINTR;
+	}
+	
+	ahci_rb_fpdma_cmd(sata, phys, blocknum);
+	ahci_port_is_t pxis = ahci_wait_event(sata);
+	
+	if ((sata->is_invalid_device) || (ahci_port_is_error(pxis))) {
+		ddf_msg(LVL_ERROR,
+		    "%s: Unrecoverable error during FPDMA read", sata->model);
+		return EINTR;
+	}
+	
+	return EOK;
+}
+
+/** Set AHCI registers for writing one sector to the SATA device, use FPDMA.
+ *
+ * @param sata     SATA device structure.
+ * @param phys     Physical address of buffer with sector data.
+ * @param blocknum Block number to write.
+ *
+ * @return EOK if succeed, error code otherwise
+ *
+ */
+static void ahci_wb_fpdma_cmd(sata_dev_t *sata, void *phys, uint64_t blocknum)
+{
+	volatile sata_ncq_command_frame_t *cmd =
+	    (sata_ncq_command_frame_t *) sata->cmd_table;
+	
+	cmd->fis_type = SATA_CMD_FIS_TYPE;
+	cmd->c = SATA_CMD_FIS_COMMAND_INDICATOR;
+	cmd->command = 0x61;
+	cmd->tag = 0;
+	cmd->control = 0;
+	
+	cmd->reserved1 = 0;
+	cmd->reserved2 = 0;
+	cmd->reserved3 = 0;
+	cmd->reserved4 = 0;
+	cmd->reserved5 = 0;
+	cmd->reserved6 = 0;
+	
+	cmd->sector_count_low = 1;
+	cmd->sector_count_high = 0;
+	
+	cmd->lba0 = blocknum & 0xff;
+	cmd->lba1 = (blocknum >> 8) & 0xff;
+	cmd->lba2 = (blocknum >> 16) & 0xff;
+	cmd->lba3 = (blocknum >> 24) & 0xff;
+	cmd->lba4 = (blocknum >> 32) & 0xff;
+	cmd->lba5 = (blocknum >> 40) & 0xff;
+	
+	volatile ahci_cmd_prdt_t *prdt =
+	    (ahci_cmd_prdt_t *) (&sata->cmd_table[0x20]);
+	
+	prdt->data_address_low = LO(phys);
+	prdt->data_address_upper = HI(phys);
+	prdt->reserved1 = 0;
+	prdt->dbc = sata->block_size - 1;
+	prdt->reserved2 = 0;
+	prdt->ioc = 0;
+	
+	sata->cmd_header->prdtl = 1;
+	sata->cmd_header->flags =
+	    AHCI_CMDHDR_FLAGS_CLEAR_BUSY_UPON_OK |
+	    AHCI_CMDHDR_FLAGS_WRITE |
+	    AHCI_CMDHDR_FLAGS_5DWCMD;
+	sata->cmd_header->bytesprocessed = 0;
+	
+	sata->port->pxsact |= 1;
+	sata->port->pxci |= 1;
+}
+
+/** Write one sector into the SATA device, use FPDMA.
+ *
+ * @param sata     SATA device structure.
+ * @param phys     Physical addres of buffer with sector data.
+ * @param blocknum Block number to write.
+ *
+ * @return EOK if succeed, error code otherwise
+ *
+ */
+static int ahci_wb_fpdma(sata_dev_t *sata, void *phys, uint64_t blocknum)
+{
+	if (sata->is_invalid_device) {
+		ddf_msg(LVL_ERROR,
+		    "%s: FPDMA write to invalid device", sata->model);
+		return EINTR;
+	}
+	
+	ahci_wb_fpdma_cmd(sata, phys, blocknum);
+	ahci_port_is_t pxis = ahci_wait_event(sata);
+	
+	if ((sata->is_invalid_device) || (ahci_port_is_error(pxis))) {
+		ddf_msg(LVL_ERROR,
+		    "%s: Unrecoverable error during FPDMA write", sata->model);
+		return EINTR;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/*-- Interrupts handling -----------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+static irq_pio_range_t ahci_ranges[] = {
+	{
+		.base = 0,
+		.size = 0,
+	}
+};
+
+static irq_cmd_t ahci_cmds[] = {
+	AHCI_PORT_CMDS(0),
+	AHCI_PORT_CMDS(1),
+	AHCI_PORT_CMDS(2),
+	AHCI_PORT_CMDS(3),
+	AHCI_PORT_CMDS(4),
+	AHCI_PORT_CMDS(5),
+	AHCI_PORT_CMDS(6),
+	AHCI_PORT_CMDS(7),
+	AHCI_PORT_CMDS(8),
+	AHCI_PORT_CMDS(9),
+	AHCI_PORT_CMDS(10),
+	AHCI_PORT_CMDS(11),
+	AHCI_PORT_CMDS(12),
+	AHCI_PORT_CMDS(13),
+	AHCI_PORT_CMDS(14),
+	AHCI_PORT_CMDS(15),
+	AHCI_PORT_CMDS(16),
+	AHCI_PORT_CMDS(17),
+	AHCI_PORT_CMDS(18),
+	AHCI_PORT_CMDS(19),
+	AHCI_PORT_CMDS(20),
+	AHCI_PORT_CMDS(21),
+	AHCI_PORT_CMDS(22),
+	AHCI_PORT_CMDS(23),
+	AHCI_PORT_CMDS(24),
+	AHCI_PORT_CMDS(25),
+	AHCI_PORT_CMDS(26),
+	AHCI_PORT_CMDS(27),
+	AHCI_PORT_CMDS(28),
+	AHCI_PORT_CMDS(29),
+	AHCI_PORT_CMDS(30),
+	AHCI_PORT_CMDS(31)
+};
+
+/** AHCI interrupt handler.
+ *
+ * @param dev   DDF device structure.
+ * @param iid   The IPC call id.
+ * @param icall The IPC call structure.
+ *
+ */
+static void ahci_interrupt(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
+{
+	ahci_dev_t *ahci = (ahci_dev_t *) dev->driver_data;
+	unsigned int port = IPC_GET_ARG1(*icall);
+	ahci_port_is_t pxis = IPC_GET_ARG2(*icall);
+	
+	if (port >= AHCI_MAX_PORTS)
+		return;
+	
+	sata_dev_t *sata = (sata_dev_t *) ahci->sata_devs[port];
+	if (sata == NULL)
+		return;
+	
+	/* Evaluate port event */
+	if ((ahci_port_is_end_of_operation(pxis)) ||
+	    (ahci_port_is_error(pxis))) {
+		fibril_mutex_lock(&sata->event_lock);
+		
+		sata->event_pxis = pxis;
+		fibril_condvar_signal(&sata->event_condvar);
+		
+		fibril_mutex_unlock(&sata->event_lock);
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI and SATA device creating and initializing routines -----------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Allocate SATA device structure with buffers for hardware.
+ *
+ * @param port AHCI port structure
+ *
+ * @return SATA device structure if succeed, NULL otherwise.
+ *
+ */
+static sata_dev_t *ahci_sata_allocate(volatile ahci_port_t *port)
+{
+	size_t size = 4096;
+	void *phys = NULL;
+	void *virt_fb = NULL;
+	void *virt_cmd = NULL;
+	void *virt_table = NULL;
+	
+	sata_dev_t *sata = malloc(sizeof(sata_dev_t));
+	if (sata == NULL)
+		return NULL;
+	
+	bzero(sata, sizeof(sata_dev_t));
+	
+	sata->port = port;
+	
+	/* Allocate and init retfis structure. */
+	int rc = dmamem_map_anonymous(size, AS_AREA_READ | AS_AREA_WRITE, 0,
+	    &phys, &virt_fb);
+	if (rc != EOK)
+		goto error_retfis;
+	
+	bzero(virt_fb, size);
+	sata->port->pxfbu = HI(phys);
+	sata->port->pxfb = LO(phys);
+	
+	/* Allocate and init command header structure. */
+	rc = dmamem_map_anonymous(size, AS_AREA_READ | AS_AREA_WRITE, 0,
+	    &phys, &virt_cmd);
+	if (rc != EOK)
+		goto error_cmd;
+	
+	bzero(virt_cmd, size);
+	sata->port->pxclbu = HI(phys);
+	sata->port->pxclb = LO(phys);
+	sata->cmd_header = (ahci_cmdhdr_t *) virt_cmd;
+	
+	/* Allocate and init command table structure. */
+	rc = dmamem_map_anonymous(size, AS_AREA_READ | AS_AREA_WRITE, 0,
+	    &phys, &virt_table);
+	if (rc != EOK)
+		goto error_table;
+	
+	bzero(virt_table, size);
+	sata->cmd_header->cmdtableu = HI(phys);
+	sata->cmd_header->cmdtable = LO(phys);
+	sata->cmd_table = (uint32_t*) virt_table;
+	
+	return sata;
+	
+error_table:
+	dmamem_unmap(virt_cmd, size);
+error_cmd:
+	dmamem_unmap(virt_fb, size);
+error_retfis:
+	free(sata);
+	return NULL;
+}
+
+/** Initialize and start SATA hardware device.
+ *
+ * @param sata SATA device structure.
+ *
+ */
+static void ahci_sata_hw_start(sata_dev_t *sata)
+{
+	ahci_port_cmd_t pxcmd;
+	
+	pxcmd.u32 = sata->port->pxcmd;
+	
+	/* Frame receiver disabled. */
+	pxcmd.fre = 0;
+	
+	/* Disable process the command list. */
+	pxcmd.st = 0;
+	
+	sata->port->pxcmd = pxcmd.u32;
+	
+	/* Clear interrupt status. */
+	sata->port->pxis = 0xffffffff;
+	
+	/* Clear error status. */
+	sata->port->pxserr = 0xffffffff;
+	
+	/* Enable all interrupts. */
+	sata->port->pxie = 0xffffffff;
+	
+	/* Frame receiver enabled. */
+	pxcmd.fre = 1;
+	
+	/* Enable process the command list. */
+	pxcmd.st = 1;
+	
+	sata->port->pxcmd = pxcmd.u32;
+}
+
+/** Create and initialize connected SATA structure device
+ *
+ * @param ahci     AHCI device structure.
+ * @param dev      DDF device structure.
+ * @param port     AHCI port structure.
+ * @param port_num Number of AHCI port with existing SATA device.
+ *
+ * @return EOK if succeed, error code otherwise.
+ *
+ */
+static int ahci_sata_create(ahci_dev_t *ahci, ddf_dev_t *dev,
+    volatile ahci_port_t *port, unsigned int port_num)
+{
+	ddf_fun_t *fun = NULL;
+	sata_dev_t *sata = ahci_sata_allocate(port);
+	if (sata == NULL)
+		return EINTR;
+	
+	/* Set pointers between SATA and AHCI structures. */
+	sata->ahci = ahci;
+	sata->port_num = port_num;
+	ahci->sata_devs[port_num] = sata;
+	
+	/* Initialize synchronization structures */
+	fibril_mutex_initialize(&sata->lock);
+	fibril_mutex_initialize(&sata->event_lock);
+	fibril_condvar_initialize(&sata->event_condvar);
+	
+	ahci_sata_hw_start(sata);
+	
+	/* Identify device. */
+	if (ahci_identify_device(sata) != EOK)
+		goto error;
+	
+	/* Set required UDMA mode */
+	if (ahci_set_highest_ultra_dma_mode(sata) != EOK)
+		goto error;
+	
+	/* Add device to the system */
+	char sata_dev_name[16];
+	snprintf(sata_dev_name, 16, "ahci_%u", sata_devices_count);
+	
+	fibril_mutex_lock(&sata_devices_count_lock);
+	sata_devices_count++;
+	fibril_mutex_unlock(&sata_devices_count_lock);
+	
+	fun = ddf_fun_create(dev, fun_exposed, sata_dev_name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function.");
+		goto error;
+	}
+	
+	fun->ops = &ahci_ops;
+	fun->driver_data = sata;
+	int rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function.");
+		goto error;
+	}
+	
+	return EOK;
+	
+error:
+	sata->is_invalid_device = true;
+	if (fun != NULL)
+		ddf_fun_destroy(fun);
+	
+	return EINTR;
+}
+
+/** Create and initialize all SATA structure devices for connected SATA drives.
+ *
+ * @param ahci AHCI device structure.
+ * @param dev  DDF device structure.
+ *
+ */
+static void ahci_sata_devices_create(ahci_dev_t *ahci, ddf_dev_t *dev)
+{
+	for (unsigned int port_num = 0; port_num < AHCI_MAX_PORTS; port_num++) {
+		/* Active ports only */
+		if (!(ahci->memregs->ghc.pi & (1 << port_num)))
+			continue;
+		
+		volatile ahci_port_t *port = ahci->memregs->ports + port_num;
+		
+		/* Active devices only */
+		ahci_port_ssts_t pxssts;
+		pxssts.u32 = port->pxssts;
+		if (pxssts.det != AHCI_PORT_SSTS_DET_ACTIVE)
+			continue;
+		
+		ahci_sata_create(ahci, dev, port, port_num);
+	}
+}
+
+/** Create AHCI device structure, intialize it and register interrupt routine.
+ *
+ * @param dev DDF device structure.
+ *
+ * @return AHCI device structure if succeed, NULL otherwise.
+ *
+ */
+static ahci_dev_t *ahci_ahci_create(ddf_dev_t *dev)
+{
+	ahci_dev_t *ahci = malloc(sizeof(ahci_dev_t));
+	if (!ahci)
+		return NULL;
+	
+	bzero(ahci, sizeof(ahci_dev_t));
+	
+	ahci->dev = dev;
+	
+	hw_res_list_parsed_t hw_res_parsed;
+	hw_res_list_parsed_init(&hw_res_parsed);
+	if (hw_res_get_list_parsed(dev->parent_sess, &hw_res_parsed, 0) != EOK)
+		goto error_get_res_parsed;
+	
+	/* Map AHCI registers. */
+	ahci->memregs = NULL;
+	
+	physmem_map((void *) (size_t) (hw_res_parsed.mem_ranges.ranges[0].address),
+	    AHCI_MEMREGS_PAGES_COUNT, AS_AREA_READ | AS_AREA_WRITE,
+	    (void **) &ahci->memregs);
+	if (ahci->memregs == NULL)
+		goto error_map_registers;
+	
+	/* Register interrupt handler */
+	ahci_ranges[0].base = (size_t) hw_res_parsed.mem_ranges.ranges[0].address;
+	ahci_ranges[0].size = sizeof(ahci_memregs_t);
+	
+	for (unsigned int port = 0; port < AHCI_MAX_PORTS; port++) {
+		size_t base = port * 7;
+		
+		ahci_cmds[base].addr =
+		    ((uint32_t *) (size_t) hw_res_parsed.mem_ranges.ranges[0].address) +
+		    AHCI_PORTS_REGISTERS_OFFSET + port * AHCI_PORT_REGISTERS_SIZE +
+		    AHCI_PORT_IS_REGISTER_OFFSET;
+		ahci_cmds[base + 2].addr = ahci_cmds[base].addr;
+		
+		ahci_cmds[base + 3].addr =
+		    ((uint32_t *) (size_t) hw_res_parsed.mem_ranges.ranges[0].address) +
+		    AHCI_GHC_IS_REGISTER_OFFSET;
+		ahci_cmds[base + 4].addr = ahci_cmds[base + 3].addr;
+	}
+	
+	irq_code_t ct;
+	ct.cmdcount = sizeof(ahci_cmds) / sizeof(irq_cmd_t);
+	ct.cmds = ahci_cmds;
+	ct.rangecount = sizeof(ahci_ranges) / sizeof(irq_pio_range_t);
+	ct.ranges = ahci_ranges;
+	
+	int rc = register_interrupt_handler(dev, hw_res_parsed.irqs.irqs[0],
+	    ahci_interrupt, &ct);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed registering interrupt handler.");
+		goto error_register_interrupt_handler;
+	}
+	
+	rc = ahci_enable_interrupt(hw_res_parsed.irqs.irqs[0]);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed enable interupt.");
+		goto error_enable_interrupt;
+	}
+	
+	hw_res_list_parsed_clean(&hw_res_parsed);
+	return ahci;
+	
+error_enable_interrupt:
+	unregister_interrupt_handler(dev, hw_res_parsed.irqs.irqs[0]);
+	
+error_register_interrupt_handler:
+	// FIXME: unmap physical memory
+	
+error_map_registers:
+	hw_res_list_parsed_clean(&hw_res_parsed);
+	
+error_get_res_parsed:
+	free(ahci);
+	return NULL;
+}
+
+/** Initialize and start AHCI hardware device.
+ *
+ * @param ahci AHCI device.
+ *
+ */
+static void ahci_ahci_hw_start(ahci_dev_t *ahci)
+{
+	/* Disable command completion coalescing feature */
+	ahci_ghc_ccc_ctl_t ccc;
+	
+	ccc.u32 = ahci->memregs->ghc.ccc_ctl;
+	ccc.en = 0;
+	ahci->memregs->ghc.ccc_ctl = ccc.u32;
+	
+	/* Set master latency timer. */
+	pci_config_space_write_8(ahci->dev->parent_sess, AHCI_PCI_MLT, 32);
+	
+	/* Enable PCI interrupt and bus mastering */
+	ahci_pcireg_cmd_t cmd;
+	
+	pci_config_space_read_16(ahci->dev->parent_sess, AHCI_PCI_CMD, &cmd.u16);
+	cmd.id = 0;
+	cmd.bme = 1;
+	pci_config_space_write_16(ahci->dev->parent_sess, AHCI_PCI_CMD, cmd.u16);
+	
+	/* Enable AHCI and interrupt. */
+	ahci->memregs->ghc.ghc = AHCI_GHC_GHC_AE | AHCI_GHC_GHC_IE;
+}
+
+/** AHCI device driver initialization
+ *
+ * Create and initialize all SATA structure devices for connected
+ * SATA drives.
+ *
+ * @param dev DDF device structure.
+ *
+ * @return EOK if succeed, error code otherwise.
+ *
+ */
+static int ahci_dev_add(ddf_dev_t *dev)	
+{
+	/* Connect to parent device */
+	dev->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    dev->handle, IPC_FLAG_BLOCKING);
+	if (dev->parent_sess == NULL)
+		return EINTR;
+	
+	ahci_dev_t *ahci = ahci_ahci_create(dev);
+	if (ahci == NULL)
+		goto error;
+	
+	dev->driver_data = ahci;
+	
+	/* Start AHCI hardware. */
+	ahci_ahci_hw_start(ahci);
+	
+	/* Create device structures for sata devices attached to AHCI. */
+	ahci_sata_devices_create(ahci, dev);
+	
+	return EOK;
+	
+error:
+	async_hangup(dev->parent_sess);
+	return EINTR;
+}
+
+/*----------------------------------------------------------------------------*/
+/*-- Helpers and utilities ---------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Convert SATA model name
+ *
+ * Convert SATA model name from machine format returned by
+ * identify device command to human readable form.
+ *
+ * @param src Source buffer with device name in machine format.
+ * @param dst Buffer for human readable string, minimum size is 41 chars.
+ *
+ */
+static void ahci_get_model_name(uint16_t *src, char *dst)
+{
+	uint8_t model[40];
+	bzero(model, 40);
+	
+	for (unsigned int i = 0; i < 20; i++) {
+		uint16_t w = src[i];
+		model[2 * i] = w >> 8;
+		model[2 * i + 1] = w & 0x00ff;
+	}
+	
+	uint32_t len = 40;
+	while ((len > 0) && (model[len - 1] == 0x20))
+		len--;
+	
+	size_t pos = 0;
+	for (unsigned int i = 0; i < len; i++) {
+		uint8_t c = model[i];
+		if (c >= 0x80)
+			c = '?';
+		
+		chr_encode(c, dst, &pos, 40);
+	}
+	
+	dst[pos] = '\0';
+}
+
+/** Enable interrupt using SERVICE_IRC.
+ *
+ * @param irq Requested irq number.
+ *
+ * @return EOK if succeed, error code otherwise.
+ *
+ */
+static int ahci_enable_interrupt(int irq)
+{
+	async_sess_t *irc_sess = NULL;
+	irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_IRC, 0, 0);
+	if (!irc_sess)
+		return EINTR;
+	
+	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);
+	
+	async_hangup(irc_sess);
+	return rc;
+}
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI Main routine -------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+	printf("%s: HelenOS AHCI device driver\n", NAME);
+	ddf_log_init(NAME, LVL_ERROR);
+	fibril_mutex_initialize(&sata_devices_count_lock);
+	return ddf_driver_main(&ahci_driver);
+}
Index: uspace/drv/block/ahci/ahci.h
===================================================================
--- uspace/drv/block/ahci/ahci.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/drv/block/ahci/ahci.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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.
+ */
+
+/** @file
+ * Header for AHCI driver.
+ */
+
+#ifndef __AHCI_H__
+#define __AHCI_H__
+
+#include <sys/types.h>
+#include <devman.h>
+#include <ddf/interrupt.h>
+#include <stdio.h>
+#include "ahci_hw.h"
+
+/** AHCI Device. */
+typedef struct {
+	/** Pointer to ddf device. */
+	ddf_dev_t *dev;
+	
+	/** Pointer to AHCI memory registers. */
+	volatile ahci_memregs_t *memregs;
+	
+	/** Pointers to sata devices. */
+	void *sata_devs[AHCI_MAX_PORTS];
+} ahci_dev_t;
+
+/** SATA Device. */
+typedef struct {
+	/** Pointer to AHCI device. */
+	ahci_dev_t *ahci;
+	
+	/** SATA port number (0-31). */
+	uint8_t port_num;
+	
+	/** Device in invalid state (disconnected and so on). */
+	bool is_invalid_device;
+	
+	/** Pointer to SATA port. */
+	volatile ahci_port_t *port;
+	
+	/** Pointer to command header. */
+	volatile ahci_cmdhdr_t *cmd_header;
+	
+	/** Pointer to command table. */
+	volatile uint32_t *cmd_table;
+	
+	/** Mutex for single operation on device. */
+	fibril_mutex_t lock;
+	
+	/** Mutex for event signaling condition variable. */
+	fibril_mutex_t event_lock;
+	
+	/** Event signaling condition variable. */
+	fibril_condvar_t event_condvar;
+	
+	/** Event interrupt state. */
+	ahci_port_is_t event_pxis;
+	
+	/** Block device service id. */
+	service_id_t service_id;
+	
+	/** Number of device data blocks. */
+	uint64_t blocks;
+	
+	/** Size of device data blocks. */
+	size_t block_size;
+	
+	/** Name of SATA device. */
+	char model[STR_BOUNDS(40) + 1];
+	
+	/** Device in invalid state (disconnected and so on). */
+	bool is_packet_device;
+	
+	/** Highest UDMA mode supported. */
+	uint8_t highest_udma_mode;
+} sata_dev_t;
+
+#endif
Index: uspace/drv/block/ahci/ahci.ma
===================================================================
--- uspace/drv/block/ahci/ahci.ma	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/drv/block/ahci/ahci.ma	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,3 @@
+10 pci/ven=8086&dev=2922
+10 pci/ven=8086&dev=2829
+10 pci/ven=1002&dev=4391
Index: uspace/drv/block/ahci/ahci_hw.h
===================================================================
--- uspace/drv/block/ahci/ahci_hw.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/drv/block/ahci/ahci_hw.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,1050 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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.
+ */
+
+/** @file
+ * Header for AHCI driver (AHCI 1.3 specification).
+ */
+
+#ifndef __AHCI_HW_H__
+#define __AHCI_HW_H__
+
+#include <sys/types.h>
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI standard constants -------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** AHCI standard 1.3 - maximum ports. */
+#define AHCI_MAX_PORTS  32
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI PCI Registers ------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** AHCI PCI register Identifiers offset. */
+#define AHCI_PCI_ID     0x00
+/** AHCI PCI register Command offset. */
+#define AHCI_PCI_CMD    0x04
+/** AHCI PCI register Device Status offset. */
+#define AHCI_PCI_STS    0x06
+/** AHCI PCI register Revision ID offset. */
+#define AHCI_PCI_RID    0x08
+/** AHCI PCI register Class Codes offset. */
+#define AHCI_PCI_CC     0x09
+/** AHCI PCI register Cache Line Size offset. */
+#define AHCI_PCI_CLS    0x0C
+/** AHCI PCI register Master Latency Timer offset. */
+#define AHCI_PCI_MLT    0x0D
+/** AHCI PCI register Header Type offset. */
+#define AHCI_PCI_HTYPE  0x0E
+/** AHCI PCI register Built In Self Test (Optional) offset. */
+#define AHCI_PCI_BIST   0x0F
+/** AHCI PCI register Other Base Address Registres (Optional). */
+#define AHCI_PCI_BAR0   0x10
+/** AHCI PCI register Other Base Address Registres (Optional). */
+#define AHCI_PCI_BAR1   0x14
+/** AHCI PCI register Other Base Address Registres (Optional). */
+#define AHCI_PCI_BAR2   0x18
+/** AHCI PCI register Other Base Address Registres (Optional). */
+#define AHCI_PCI_BAR3   0x1C
+/** AHCI PCI register Other Base Address Registres (Optional). */
+#define AHCI_PCI_BAR4   0x20
+/** AHCI PCI register AHCI Base Address offset. */
+#define AHCI_PCI_ABAR   0x24
+/** AHCI PCI register Subsystem Identifiers offset. */
+#define AHCI_PCI_SS     0x2C
+/** AHCI PCI register Expansion ROM Base Address (Optional) offset. */
+#define AHCI_PCI_EROM   0x30
+/** AHCI PCI register Capabilities Pointer offset. */
+#define AHCI_PCI_CAP    0x34
+/** AHCI PCI register Interrupt Information offset. */
+#define AHCI_PCI_INTR   0x3C
+/** AHCI PCI register Min Grant (Optional) offset. */
+#define AHCI_PCI_MGNT   0x3E
+/** AHCI PCI register Max Latency (Optional) offset. */
+#define AHCI_PCI_MLAT   0x3F
+
+/** AHCI PCI register Identifiers. */
+typedef struct {
+	/** Indicates the company vendor assigned by the PCI SIG. */
+	uint16_t vendorid;
+	/** Indicates what device number assigned by the vendor */
+	uint16_t deviceid;
+} ahci_pcireg_id_t;
+
+/** AHCI PCI register Command. */
+typedef union {
+	struct {
+		/** I/O Space Enable. */
+		unsigned int iose : 1;
+		/** Memory Space Enable. */
+		unsigned int mse : 1;
+		/** Bus Master Enable. */
+		unsigned int bme : 1;
+		/** Special Cycle Enable. */
+		unsigned int sce : 1;
+		/** Memory Write and Invalidate Enable. */
+		unsigned int mwie : 1;
+		/** VGA Palette Snooping Enable. */
+		unsigned int vga : 1;
+		/** Parity Error Response Enable. */
+		unsigned int pee : 1;
+		/** Wait Cycle Enable. */
+		unsigned int wcc : 1;
+		/** SERR# Enable. */
+		unsigned int see : 1;
+		/** Fast Back-to-Back Enable. */
+		unsigned int fbe : 1;
+		/** Interrupt Disable - disables the HBA from generating interrupts.
+		 * This bit does not have any effect on MSI operation.
+		 */
+		unsigned int id : 1;
+		/** Reserved. */
+		unsigned int reserved : 5;
+	};
+	uint16_t u16;
+} ahci_pcireg_cmd_t;
+
+/** AHCI PCI register Command - Interrupt Disable bit. */
+#define AHCI_PCIREG_CMD_ID  0x0400
+
+/** AHCI PCI register Command - Bus Master Enable bit. */
+#define AHCI_PCIREG_CMD_BME  0x0004
+
+/** AHCI PCI register Device status. */
+typedef union {
+	struct {
+		/** Reserved. */
+		unsigned int reserved1 : 3;
+		/** Indicate the interrupt status of the device (1 = asserted). */
+		unsigned int is : 1;
+		/** Indicates presence of capatibility list. */
+		unsigned int cl : 1;
+		/** 66 Mhz capable. */
+		unsigned int c66 : 1;
+		/** Reserved. */
+		unsigned int reserved2 : 1;
+		/** Fast back to back capable. */
+		unsigned int fbc : 1;
+		/** Master data parity error detected. */
+		unsigned int dpd : 1;
+		/** Device select timing. */
+		unsigned int devt : 2;
+		/** Signaled target abort. */
+		unsigned int sta : 1;
+		/** Received target abort. */
+		unsigned int rta : 1;
+		/** Received master abort. */
+		unsigned int rma : 1;
+		/** Signaled system error. */
+		unsigned int sse : 1;
+		/** Detected parity error. */
+		unsigned int dpe : 1;
+	};
+	uint16_t u16;
+} ahci_pcireg_sts_t;
+
+/** AHCI PCI register Revision ID. */
+typedef struct {
+	/** Indicates stepping of the HBA hardware. */
+	uint8_t u8;
+} ahci_pcireg_rid_t;
+
+/** AHCI PCI register Class Codes. */
+typedef struct {
+	/** Programing interface, when set to 01h and the scc is set to 06h,
+	 * indicates that this an AHCI HBA major revision 1.
+	 */
+	uint8_t pi;
+	/** When set to 06h, indicates that is a SATA device. */
+	uint8_t scc;
+	/** Value 01 indicates that is a mass storage device. */
+	uint8_t bcc;
+} ahci_pcireg_cc_t_t;
+
+/** AHCI PCI register Cache Line Size. */
+typedef struct {
+	/** Cache line size for use with the memory write and invalidate command. */
+	uint8_t u8;
+} ahci_pcireg_cls_t;
+
+/** AHCI PCI register Master Latency Timer. */
+typedef struct {
+	/** Master latency timer,indicates the number of clocks the HBA is allowed
+	 * to acts as master on PCI.
+	 */
+	uint8_t u8;
+} ahci_pcireg_mlt_t;
+
+/** AHCI PCI register Header Type. */
+typedef union {
+	struct {
+		/** Header layout. */
+		unsigned int hl : 7;
+		/** Multi function device flag. */
+		unsigned int mfd : 1;
+	};
+	uint8_t u8;
+} ahci_pciregs_htype_t;
+
+/** AHCI PCI register Built in self test. */
+typedef union {
+	struct {
+	/** Indicates the completion status of BIST
+	 * non-zero value indicates a failure.
+	 */
+	unsigned int cc : 4;
+	/** Reserved. */
+	unsigned int reserved : 2;
+	/** Software sets this bit to 1 to invoke BIST,
+	 * the HBA clears this bit to 0 when BIST is complete.
+	 */
+	unsigned int sb : 1;
+	/** BIST capable. */
+	unsigned int bc : 1;
+	};
+	uint8_t u8;
+} ahci_pciregs_bist_t;
+
+/** AHCI PCI register AHCI Base Address <BAR 5>. */
+typedef union {
+	struct {
+		/** Indicates a request for register memory space. */
+		unsigned int rte : 1;
+		/** Indicates the this range can be mapped anywhere in 32-bit address
+		 * space.
+		 */
+		unsigned int tp : 2;
+		/** Indicate that this range is not prefetchable. */
+		unsigned int pf : 1;
+		/** Reserved. */
+		unsigned int reserved : 9;
+		/** Base address of registry memory space. */
+		unsigned int ba : 19;
+	};
+	uint32_t u32;
+} ahci_pciregs_abar_t;
+
+/** AHCI PCI register Subsystem Identifiers. */
+typedef struct
+{
+	/** Sub system vendor identifier. */
+	uint8_t ssvid;
+	/** Sub system identifier. */
+	uint8_t ssid;
+} ahci_pcireg_ss_t;
+
+/** AHCI PCI registers Expansion ROM Base Address. */
+typedef struct
+{
+	/** Indicates the base address of the HBA expansion ROM. */
+	uint32_t u32;
+} ahci_pcireg_erom_t;
+
+/** AHCI PCI register Capabilities Pointer. */
+typedef struct
+{
+	/** Indicates the first capability pointer offset. */
+	uint8_t u8;
+} ahci_pcireg_cap_t;
+
+/** AHCI PCI register Interrupt Information. */
+typedef struct
+{
+	/* Software written value to indicate which interrupt vector
+	 * the interrupt is connected to.
+	 */
+	uint8_t iline;
+	/** This indicates the interrupt pin the HBA uses. */
+	uint8_t ipin;
+} ahci_pcireg_intr;
+
+/** AHCI PCI register Min Grant (Optional). */
+typedef struct
+{
+	/** Indicates the minimum grant time that the device
+	 * wishes grant asserted.
+	 */
+	uint8_t u8;
+} ahci_pcireg_mgnt_t;
+
+/** AHCI PCI register Max Latency (Optional). */
+typedef struct
+{
+	/** Indicates the maximum latency that the device can withstand. */
+	uint8_t u8;
+} ahci_pcireg_mlat_t;
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI Memory Registers ---------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Number of pages for ahci memory registers. */
+#define AHCI_MEMREGS_PAGES_COUNT  8
+
+/** AHCI Memory register Generic Host Control - HBA Capabilities. */
+typedef union {
+	struct {
+		/** Number of Ports. */
+		unsigned int np : 5;
+		/** Supports External SATA. */
+		unsigned int sxs : 1;
+		/** Enclosure Management Supported. */
+		unsigned int ems : 1;
+		/** Command Completion Coalescing Supported. */
+		unsigned int cccs : 1;
+		/** Number of Command Slots. */
+		unsigned int ncs : 5;
+		/** Partial State Capable. */
+		unsigned int psc : 1;
+		/** Slumber State Capable. */
+		unsigned int ssc : 1;
+		/** PIO Multiple DRQ Block. */
+		unsigned int pmd : 1;
+		/** FIS-based Switching Supported. */
+		unsigned int fbss : 1;
+		/** Supports Port Multiplier. */
+		unsigned int spm : 1;
+		/** Supports AHCI mode only. */
+		unsigned int sam : 1;
+		/** Reserved. */
+		unsigned int reserved : 1;
+		/** Interface Speed Support. */
+		unsigned int iss : 4;
+		/** Supports Command List Override. */
+		unsigned int sclo : 1;
+		/** Supports Activity LED. */
+		unsigned int sal : 1;
+		/** Supports Aggressive Link Power Management. */
+		unsigned int salp : 1;
+		/** Supports Staggered Spin-up. */
+		unsigned int sss : 1;
+		/** Supports Mechanical Presence Switch. */
+		unsigned int smps : 1;
+		/** Supports SNotification Register. */
+		unsigned int ssntf : 1;
+		/** Supports Native Command Queuing. */
+		unsigned int sncq : 1;
+		/** Supports 64-bit Addressing. */
+		unsigned int s64a : 1;
+	};
+	uint32_t u32;
+} ahci_ghc_cap_t;
+
+/** AHCI Memory register Generic Host Control Global Host Control. */
+typedef union {
+	struct {
+		/** HBA Reset. */
+		unsigned int hr : 1;
+		/** Interrupt Enable. */
+		unsigned int ie : 1;
+		/** MSI Revert to Single Message. */
+		unsigned int mrsm : 1;
+		/** Reserved. */
+		unsigned int reserved : 28;
+		/** AHCI Enable. */
+		unsigned int ae : 1;
+	};
+	uint32_t u32;
+} ahci_ghc_ghc_t;
+
+/** AHCI Enable mask bit. */
+#define AHCI_GHC_GHC_AE  0x80000000
+
+/** AHCI Interrupt Enable mask bit. */
+#define AHCI_GHC_GHC_IE  0x00000002
+
+/** AHCI Memory register Interrupt pending register. */
+typedef uint32_t ahci_ghc_is_t;
+
+/** AHCI GHC register offset. */
+#define AHCI_GHC_IS_REGISTER_OFFSET  2
+
+/** AHCI ports registers offset. */
+#define AHCI_PORTS_REGISTERS_OFFSET  64
+
+/** AHCI port registers size. */
+#define AHCI_PORT_REGISTERS_SIZE  32
+
+/** AHCI port IS register offset. */
+#define AHCI_PORT_IS_REGISTER_OFFSET  4
+
+/** AHCI Memory register Ports implemented. */
+typedef struct {
+	/** If a bit is set to 1, the corresponding port
+	 * is available for software use.
+	 */
+	uint32_t u32;
+} ahci_ghc_pi_t;
+
+/** AHCI Memory register AHCI version. */
+typedef struct {
+	/** Indicates the minor version */
+	uint16_t mnr;
+	/** Indicates the major version */
+	uint16_t mjr;
+} ahci_ghc_vs_t;
+
+/** AHCI Memory register Command completion coalesce control. */
+typedef union {
+	struct {
+		/** Enable CCC features. */
+		unsigned int en : 1;
+		/** Reserved. */
+		unsigned int reserved : 2;
+		/** Interrupt number for CCC. */
+		unsigned int intr : 5;
+		/** Number of command completions that are necessary to cause
+		 * a CCC interrupt.
+		 */
+		uint8_t cc;
+		/** Timeout value in  ms. */
+		uint16_t tv;
+	};
+	uint32_t u32;
+} ahci_ghc_ccc_ctl_t;
+
+/** AHCI Memory register Command completion coalescing ports. */
+typedef struct
+{
+	/** If a bit is set to 1, the corresponding port is
+	 * part of the command completion coalescing feature.
+	 */
+	uint32_t u32;
+} ahci_ghc_ccc_ports_t;
+
+/** AHCI Memory register Enclosure management location. */
+typedef struct
+{
+	/** Size of the transmit message buffer area in dwords. */
+	uint16_t sz;
+	/*
+	 * Offset of the transmit message buffer area in dwords
+	 * from the beginning of ABAR
+	 */
+	uint16_t ofst;
+} ahci_ghc_em_loc;
+
+/** AHCI Memory register Enclosure management control. */
+typedef union {
+	struct {
+		/** Message received. */
+		unsigned int mr : 1;
+		/** Reserved. */
+		unsigned int reserved : 7;
+		/** Transmit message. */
+		unsigned int tm : 1;
+		/** Reset. */
+		unsigned int rst : 1;
+		/** Reserved. */
+		unsigned int reserved2 : 6;
+		/** LED message types. */
+		unsigned int led : 1;
+		/** Support SAFT-TE message type. */
+		unsigned int safte : 1;
+		/** Support SES-2 message type. */
+		unsigned int ses2 : 1;
+		/** Support SGPIO register. */
+		unsigned int sgpio : 1;
+		/** Reserved. */
+		unsigned int reserved3 : 4;
+		/** Single message buffer. */
+		unsigned int smb : 1;
+		/**  Support transmitting only. */
+		unsigned int xmt : 1;
+		/** Activity LED hardware driven. */
+		unsigned int alhd : 1;
+		/** Port multiplier support. */
+		unsigned int pm : 1;
+		/** Reserved. */
+		unsigned int reserved4 : 4;
+	};
+	uint32_t u32;
+} ahci_ghc_em_ctl_t;
+
+/** AHCI Memory register HBA capatibilities extended. */
+typedef union {
+	struct {
+		/** HBA support BIOS/OS handoff mechanism,
+		 * implemented BOHC register.
+		 */
+		unsigned int boh : 1;
+		/** Support for NVMHCI register. */
+		unsigned int nvmp : 1;
+		/** Automatic partial to slumber transition support. */
+		unsigned int apst : 1;
+		/** Reserved. */
+		unsigned int reserved : 29;
+	};
+	uint32_t u32;
+} ahci_ghc_cap2_t;
+
+/** AHCI Memory register BIOS/OS Handoff control and status. */
+typedef union {
+	struct {
+		/** BIOS Owned semaphore. */
+		unsigned int bos : 1;
+		/** OS Owned semaphore. */
+		unsigned int oos : 1;
+		/** SMI on OS ownership change enable. */
+		unsigned int sooe : 1;
+		/** OS ownership change. */
+		unsigned int ooc : 1;
+		/** BIOS Busy. */
+		unsigned int bb : 1;
+		/** Reserved. */
+		unsigned int reserved : 27;
+	};
+	uint32_t u32;
+} ahci_ghc_bohc_t;
+
+/** AHCI Memory register Generic Host Control. */
+typedef struct
+{
+	/** Host Capabilities */
+	uint32_t cap;
+	/** Global Host Control */
+	uint32_t ghc;
+	/** Interrupt Status */
+	ahci_ghc_is_t is;
+	/** Ports Implemented */
+	uint32_t pi;
+	/** Version */
+	uint32_t vs;
+	/** Command Completion Coalescing Control */
+	uint32_t ccc_ctl;
+	/** Command Completion Coalescing Ports */
+	uint32_t ccc_ports;
+	/** Enclosure Management Location */
+	uint32_t em_loc;
+	/** Enclosure Management Control */
+	uint32_t em_ctl;
+	/** Host Capabilities Extended */
+	uint32_t cap2;
+	/** BIOS/OS Handoff Control and Status */
+	uint32_t bohc;
+} ahci_ghc_t;
+
+/** AHCI Memory register Port x Command List Base Address. */
+typedef union {
+	struct {
+		/** Reserved. */
+		unsigned int reserved : 10;
+		/** Command List Base Address (CLB) - Indicates the 32-bit base physical
+		 * address for the command list for this port. This base is used when
+		 * fetching commands to execute. The structure pointed to by this
+		 * address range is 1K-bytes in length. This address must be 1K-byte
+		 * aligned as indicated by bits 09:00 being read only.
+		 */
+		unsigned int clb : 22;
+	};
+	uint32_t u32;
+} ahci_port_clb_t;
+
+/** AHCI Memory register Port x Command List Base Address Upper 32-Bits. */
+typedef struct {
+	/** Command List Base Address Upper (CLBU): Indicates the upper 32-bits
+	 * for the command list base physical address for this port. This base
+	 * is used when fetching commands to execute. This register shall
+	 * be read only for HBAs that do not support 64-bit addressing.
+	 */
+	uint32_t u32;
+} ahci_port_clbu_t;
+
+/** AHCI Memory register Port x FIS Base Address. */
+typedef union {
+	struct {
+		/** Reserved. */
+		unsigned int reserved : 8;
+		/** FIS Base Address (FB) - Indicates the 32-bit base physical address
+		 * for received FISes. The structure pointed to by this address range
+		 * is 256 bytes in length. This address must be 256-byte aligned as
+		 * indicated by bits 07:00 being read only. When FIS-based switching
+		 * is in use, this structure is 4KB in length and the address shall be
+		 * 4KB aligned.
+		 */
+		unsigned int fb : 24;
+	};
+	uint32_t u32;
+} ahci_port_fb_t;
+
+/** AHCI Memory register Port x FIS Base Address Upper 32-Bits. */
+typedef struct {
+	/** FIS Base Address Upper (FBU) - Indicates the upper 32-bits
+	 * for the received FIS base physical address for this port. This register
+	 * shall be read only for HBAs that do not support 64-bit addressing.
+	 */
+	uint32_t u32;
+} ahci_port_fbu_t;
+
+/** AHCI Memory register Port x Interrupt Status. */
+typedef uint32_t ahci_port_is_t;
+
+#define AHCI_PORT_IS_DHRS  (1 << 0)
+#define AHCI_PORT_IS_PSS   (1 << 1)
+#define AHCI_PORT_IS_DSS   (1 << 2)
+#define AHCI_PORT_IS_SDBS  (1 << 3)
+#define AHCI_PORT_IS_UFS   (1 << 4)
+#define AHCI_PORT_IS_DPS   (1 << 5)
+#define AHCI_PORT_IS_PCS   (1 << 6)
+#define AHCI_PORT_IS_DMPS  (1 << 7)
+
+#define AHCI_PORT_IS_PRCS  (1 << 22)
+#define AHCI_PORT_IS_IPMS  (1 << 23)
+#define AHCI_PORT_IS_OFS   (1 << 24)
+#define AHCI_PORT_IS_INFS  (1 << 26)
+#define AHCI_PORT_IS_IFS   (1 << 27)
+#define AHCI_PORT_IS_HDBS  (1 << 28)
+#define AHCI_PORT_IS_HBFS  (1 << 29)
+#define AHCI_PORT_IS_TFES  (1 << 30)
+#define AHCI_PORT_IS_CPDS  (1 << 31)
+
+#define AHCI_PORT_END_OF_OPERATION \
+	(AHCI_PORT_IS_DHRS | \
+	AHCI_PORT_IS_SDBS )
+
+#define AHCI_PORT_IS_ERROR \
+	(AHCI_PORT_IS_UFS | \
+	AHCI_PORT_IS_PCS | \
+	AHCI_PORT_IS_DMPS | \
+	AHCI_PORT_IS_PRCS | \
+	AHCI_PORT_IS_IPMS | \
+	AHCI_PORT_IS_OFS | \
+	AHCI_PORT_IS_INFS | \
+	AHCI_PORT_IS_IFS | \
+	AHCI_PORT_IS_HDBS | \
+	AHCI_PORT_IS_HBFS | \
+	AHCI_PORT_IS_TFES | \
+	AHCI_PORT_IS_CPDS)
+
+#define AHCI_PORT_IS_PERMANENT_ERROR \
+	(AHCI_PORT_IS_PCS | \
+	AHCI_PORT_IS_DMPS | \
+	AHCI_PORT_IS_PRCS | \
+	AHCI_PORT_IS_IPMS | \
+	AHCI_PORT_IS_CPDS )
+
+/** Evaluate end of operation status from port interrupt status.
+ *
+ * @param port_is Value of port interrupt status.
+ *
+ * @return Indicate end of operation status.
+ *
+ */
+static inline int ahci_port_is_end_of_operation(ahci_port_is_t port_is)
+{
+	return port_is & AHCI_PORT_END_OF_OPERATION;
+}
+
+/** Evaluate error status from port interrupt status.
+ *
+ * @param port_is Value of port interrupt status.
+ *
+ * @return Indicate error status.
+ *
+ */
+static inline int ahci_port_is_error(ahci_port_is_t port_is)
+{
+	return port_is & AHCI_PORT_IS_ERROR;
+}
+
+/** Evaluate permanent error status from port interrupt status.
+ *
+ * @param port_is Value of port interrupt status.
+ *
+ * @return Indicate permanent error status.
+ *
+ */
+static inline int ahci_port_is_permanent_error(ahci_port_is_t port_is)
+{
+	return port_is & AHCI_PORT_IS_PERMANENT_ERROR;
+}
+
+/** Evaluate task file error status from port interrupt status.
+ *
+ * @param port_is Value of port interrupt status.
+ *
+ * @return Indicate error status.
+ *
+ */
+static inline int ahci_port_is_tfes(ahci_port_is_t port_is)
+{
+	return port_is & AHCI_PORT_IS_TFES;
+}
+
+/** AHCI Memory register Port x Interrupt Enable. */
+typedef union {
+	struct {
+		/** Device to Host Register FIS Interrupt Enable. */
+		unsigned int dhre : 1;
+		/** PIO Setup FIS Interrupt Enable. */
+		unsigned int pse : 1;
+		/** DMA Setup FIS Interrupt Enable. */
+		unsigned int dse : 1;
+		/** Set Device Bits Interrupt Eenable. */
+		unsigned int sdbe : 1;
+		/** Unknown FIS Interrupt Enable. */
+		unsigned int ufe : 1;
+		/** Descriptor Processed Interrupt Enable. */
+		unsigned int dpe : 1;
+		/** Port Change Interrupt Enable. */
+		unsigned int pce : 1;
+		/** Device Mechanical Presence Enable. */
+		unsigned int dmpe : 1;
+		/** Reserved. */
+		unsigned int reserved1 : 14;
+		/** PhyRdy Change Interrupt Enable. */
+		unsigned int prce : 1;
+		/** Incorrect Port Multiplier Enable. */
+		unsigned int ipme : 1;
+		/** Overflow Status Enable. */
+		unsigned int ofe : 1;
+		/** Reserved. */
+		unsigned int reserved2 : 1;
+		/** Interface Non-fatal Error Enable. */
+		unsigned int infe : 1;
+		/** Interface Fatal Error Enable. */
+		unsigned int ife : 1;
+		/** Host Bus Data Error Enable. */
+		unsigned int hbde : 1;
+		/** Host Bus Fatal Error Enable. */
+		unsigned int hbfe : 1;
+		/** Task File Error Enable. */
+		unsigned int tfee : 1;
+		/** Cold Port Detect Enable. */
+		unsigned int cpde : 1;
+	};
+	uint32_t u32;
+} ahci_port_ie_t;
+
+/** AHCI Memory register Port x Command and Status. */
+typedef union {
+	struct {
+		/** Start - when set, the HBA may process the command list. */
+		unsigned int st : 1;
+		/** Spin-Up Device. */
+		unsigned int sud : 1;
+		/** Power On Device. */
+		unsigned int pod : 1;
+		/** Command List Override. */
+		unsigned int clo : 1;
+		/** FIS Receive Enable. */
+		unsigned int fre : 1;
+		/** Reserved. */
+		unsigned int reserved : 3;
+		/** Current Command Slot. */
+		unsigned int ccs : 5;
+		/** Mechanical Presence Switch State. */
+		unsigned int mpss : 1;
+		/** FIS Receive Running. */
+		unsigned int fr : 1;
+		/** Command List Running. */
+		unsigned int cr : 1;
+		/** Cold Presence State. */
+		unsigned int cps : 1;
+		/** Port Multiplier Attached. */
+		unsigned int pma : 1;
+		/** Hot Plug Capable Port. */
+		unsigned int hpcp : 1;
+		/** Mechanical Presence Switch Attached to Port. */
+		unsigned int mpsp : 1;
+		/** Cold Presence Detection. */
+		unsigned int cpd : 1;
+		/** External SATA Port. */
+		unsigned int esp : 1;
+		/** FIS-based Switching Capable Port. */
+		unsigned int fbscp : 1;
+		/** Automatic Partial to Slumber Transitions Enabled. */
+		unsigned int apste : 1;
+		/** Device is ATAPI. */
+		unsigned int atapi : 1;
+		/** Drive LED on ATAPI Enable. */
+		unsigned int dlae : 1;
+		/** Aggressive Link Power Management Enable. */
+		unsigned int alpe : 1;
+		/** Aggressive Slumber / Partial. */
+		unsigned int asp : 1;
+		/** Interface Communication Control.
+		 * Values:
+		 * 7h - fh Reserved,
+		 * 6h Slumber - This shall cause the HBA to request a transition
+		 * of the interface to the Slumber state,
+		 * 3h - 5h Reserved,
+		 * 2h Partial - This shall cause the HBA to request a transition
+		 * of the interface to the Partial state,
+		 * 1h Active,
+		 * 0h No-Op / Idle.
+		 */
+		unsigned int icc : 4;
+	};
+	uint32_t u32;
+} ahci_port_cmd_t;
+
+/** AHCI Memory register Port x Task File Data. */
+typedef union {
+	struct {
+		/** Status (STS): Contains the latest copy of the task file
+		 * status register.
+		 */
+		uint8_t sts;
+		/** Error (ERR) - Contains the latest copy of the task file
+		 * error register.
+		 */
+		uint8_t err;
+		/** Reserved. */
+		uint16_t reserved;
+	};
+	uint32_t u32;
+} ahci_port_tfd_t;
+
+/** AHCI Memory register Port x Signature. */
+typedef union {
+	struct {
+		/** Sector Count Register */
+		uint8_t sector_count;
+		/** LBA Low Register */
+		uint8_t lba_lr;
+		/** LBA Mid Register */
+		uint8_t lba_mr;
+		/** LBA High Register */
+		uint8_t lba_hr;
+	};
+	uint32_t u32;
+} ahci_port_sig_t;
+
+/** AHCI Memory register Port x Serial ATA Status (SCR0: SStatus). */
+typedef union {
+	struct {
+		/** Device Detection */
+		unsigned int det : 4;
+		/** Current Interface Speed */
+		unsigned int spd : 4;
+		/** Interface Power Management */
+		unsigned int ipm : 4;
+		/** Reserved. */
+		unsigned int reserved : 20;
+	};
+	uint32_t u32;
+} ahci_port_ssts_t;
+
+/** Device detection active status. */
+#define AHCI_PORT_SSTS_DET_ACTIVE  3
+
+/** AHCI Memory register Port x Serial ATA Control (SCR2: SControl). */
+typedef union {
+	struct {
+		/** Device Detection Initialization */
+		unsigned int det : 4;
+		/** Speed Allowed */
+		unsigned int spd : 4;
+		/** Interface Power Management Transitions Allowed */
+		unsigned int ipm : 4;
+		/** Reserved. */
+		unsigned int reserved : 20;
+	};
+	uint32_t u32;
+} ahci_port_sctl_t;
+
+/** AHCI Memory register Port x Port x Serial ATA Error (SCR1: SError). */
+typedef struct {
+	/** Error (ERR) - The ERR field contains error information for use
+	 * by host software in determining the appropriate response to the
+	 * error condition.
+	 */
+	uint16_t err;
+	/** Diagnostics (DIAG) - Contains diagnostic error information for use
+	 * by diagnostic software in validating correct operation or isolating
+	 * failure modes.
+	 */
+	uint16_t diag;
+} ahci_port_serr_t;
+
+/** AHCI Memory register Port x Serial ATA Active (SCR3: SActive). */
+typedef struct {
+	/** Device Status - Each bit corresponds to the TAG and
+	 * command slot of a native queued command, where bit 0 corresponds
+	 * to TAG 0 and command slot 0.
+	 */
+	uint32_t u32;
+} ahci_port_sact_t;
+
+/** AHCI Memory register Port x Command Issue. */
+typedef struct {
+	/** Commands Issued - Each bit corresponds to a command slot,
+	 *  where bit 0 corresponds to command slot 0.
+	 */
+	uint32_t u32;
+} ahci_port_ci_t;
+
+/** AHCI Memory register Port x Serial ATA Notification
+ * (SCR4: SNotification).
+ */
+typedef struct {
+	/** PM Notify (PMN): This field indicates whether a particular device with
+	 * the corresponding PM Port number issued a Set Device Bits FIS
+	 * to the host with the Notification bit set.
+	 */
+	uint16_t pmn;
+	/** Reserved. */
+	uint16_t reserved;
+} ahci_port_sntf_t;
+
+/** AHCI Memory register Port x FIS-based Switching Control.
+ * This register is used to control and obtain status
+ * for Port Multiplier FIS-based switching.
+ */
+typedef union {
+	struct {
+		/** Enable */
+		unsigned int en : 1;
+		/** Device Error Clear */
+		unsigned int dec : 1;
+		/** Single Device Error */
+		unsigned int sde : 1;
+		/** Reserved. */
+		unsigned int reserved1 : 5;
+		/** Device To Issue */
+		unsigned int dev : 1;
+		/** Active Device Optimization */
+		unsigned int ado : 1;
+		/** Device With Error */
+		unsigned int dwe : 1;
+		/** Reserved. */
+		unsigned int reserved2 : 1;
+	};
+	uint32_t u32;
+} ahci_port_fbs_t;
+
+/** AHCI Memory register Port. */
+typedef volatile struct
+{
+	/** Port x Command List Base Address. */
+	uint32_t pxclb;
+	/** Port x Command List Base Address Upper 32-Bits. */
+	uint32_t pxclbu;
+	/** Port x FIS Base Address. */
+	uint32_t pxfb;
+	/** Port x FIS Base Address Upper 32-Bits. */
+	uint32_t pxfbu;
+	/** Port x Interrupt Status. */
+	ahci_port_is_t pxis;
+	/** Port x Interrupt Enable. */
+	uint32_t pxie;
+	/** Port x Command and Status. */
+	uint32_t pxcmd;
+	/** Reserved. */
+	uint32_t reserved1;
+	/** Port x Task File Data. */
+	uint32_t pxtfd;
+	/**  Port x Signature. */
+	uint32_t pxsig;
+	/** Port x Serial ATA Status (SCR0: SStatus). */
+	uint32_t pxssts;
+	/** Port x Serial ATA Control (SCR2: SControl). */
+	uint32_t pxsctl;
+	/** Port x Serial ATA Error (SCR1: SError). */
+	uint32_t pxserr;
+	/** Port x Serial ATA Active (SCR3: SActive). */
+	uint32_t pxsact;
+	/** Port x Command Issue. */
+	uint32_t pxci;
+	/** Port x Serial ATA Notification (SCR4: SNotification). */
+	uint32_t pxsntf;
+	/** Port x FIS-based Switching Control. */
+	uint32_t pxfbs;
+	/** Reserved. */
+	uint32_t reserved2[11];
+	/** Port x Vendor Specific. */
+	uint32_t pxvs[4];
+} ahci_port_t;
+
+/** AHCI Memory Registers. */
+typedef volatile struct {
+	/** Generic Host Control. */
+	ahci_ghc_t ghc;
+	/** Reserved. */
+	uint32_t reserved[13];
+	/** Reserved for NVMHCI. */
+	uint32_t reservedfornvmhci[16];
+	/** Vendor Specific registers. */
+	uint32_t vendorspecificsregs[24];
+	/** Ports. */
+	ahci_port_t ports[AHCI_MAX_PORTS];
+} ahci_memregs_t;
+
+/** AHCI Command header entry.
+ *
+ * This structure is not an AHCI register.
+ *
+ */
+typedef volatile struct {
+	/** Flags. */
+	uint16_t flags;
+	/** Physical Region Descriptor Table Length. */
+	uint16_t prdtl;
+	/** Physical Region Descriptor Byte Count. */
+	uint32_t bytesprocessed;
+	 /** Command Table Descriptor Base Address. */
+	uint32_t cmdtable;
+	/** Command Table Descriptor Base Address Upper 32-bits. */
+	uint32_t cmdtableu;
+} ahci_cmdhdr_t;
+
+/** Clear Busy upon R_OK (C) flag. */
+#define AHCI_CMDHDR_FLAGS_CLEAR_BUSY_UPON_OK  0x0400
+
+/** Write operation flag. */
+#define AHCI_CMDHDR_FLAGS_WRITE  0x0040
+
+/** 2 DW length command flag. */
+#define AHCI_CMDHDR_FLAGS_2DWCMD  0x0002
+
+/** 5 DW length command flag. */
+#define AHCI_CMDHDR_FLAGS_5DWCMD  0x0005
+
+/** AHCI Command Physical Region Descriptor entry.
+ *
+ * This structure is not an AHCI register.
+ *
+ */
+typedef volatile struct {
+	/** Word aligned 32-bit data base address. */
+	uint32_t data_address_low;
+	/** Upper data base address, valid only for 64-bit HBA addressing. */
+	uint32_t data_address_upper;
+	/** Reserved. */
+	uint32_t reserved1;
+	/** Data byte count */
+	unsigned int dbc : 22;
+	/** Reserved */
+	unsigned int reserved2 : 9;
+	/** Set Interrupt on each operation completion */
+	unsigned int ioc : 1;
+} ahci_cmd_prdt_t;
+
+#endif
Index: uspace/drv/block/ahci/ahci_sata.h
===================================================================
--- uspace/drv/block/ahci/ahci_sata.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/drv/block/ahci/ahci_sata.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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.
+ */
+
+/** @file
+ * Header for AHCI driver (SATA/ATA and related things).
+ */
+
+#ifndef __AHCI_SATA_H__
+#define __AHCI_SATA_H__
+
+#include <sys/types.h>
+
+/*----------------------------------------------------------------------------*/
+/*-- SATA Buffer Lengths -----------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Default sector size in bytes. */
+#define SATA_DEFAULT_SECTOR_SIZE  512
+
+/** Size for set feature command buffer in bytes. */
+#define SATA_SET_FEATURE_BUFFER_LENGTH  512
+
+/** Size for indentify (packet) device buffer in bytes. */
+#define SATA_IDENTIFY_DEVICE_BUFFER_LENGTH  512
+
+/*----------------------------------------------------------------------------*/
+/*-- SATA Fis Frames ---------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Sata FIS Type number. */
+#define SATA_CMD_FIS_TYPE  0x27
+
+/** Sata FIS Type command indicator. */
+#define SATA_CMD_FIS_COMMAND_INDICATOR  0x80
+
+/** Standard Command frame. */
+typedef struct {
+	/** FIS type - always SATA_CMD_FIS_TYPE. */
+	unsigned int fis_type : 8;
+	/** Indicate that FIS is a Command - always SATA_CMD_FIS_COMMAND_INDICATOR. */
+	unsigned int c : 8;
+	/** Command - Identity device - 0xec, Set fetures - 0xef. */
+	unsigned int command : 8;
+	/** Features - subcommand for set features - set tranfer mode - 0x03. */
+	unsigned int features : 8;
+	/** 0:23 bits of LBA. */
+	unsigned int lba_lower : 24;
+	/** Device. */
+	unsigned int device : 8;
+	/** 24:47 bits of LBA. */
+	unsigned int lba_upper : 24;
+	/** Features - subcommand for set features - set tranfer mode - 0x03. */
+	unsigned int features_upper : 8;
+	/** Sector count - transfer mode for set transfer mode operation. */
+	unsigned int count : 16;
+	/** Reserved. */
+	unsigned int reserved1 : 8;
+	/** Control. */
+	unsigned int control : 8;
+	/** Reserved. */
+	unsigned int reserved2 : 32;
+} sata_std_command_frame_t;
+
+/** Command frame for NCQ data operation. */
+typedef struct {
+	/** FIS type - always 0x27. */
+	uint8_t fis_type;
+	/** Indicate that FIS is a Command - always SATA_CMD_FIS_COMMAND_INDICATOR. */
+	uint8_t c;
+	/** Command - FPDMA Read - 0x60, FPDMA Write - 0x61. */
+	uint8_t command;
+	/** bits 7:0 of sector count. */
+	uint8_t sector_count_low;
+	/** bits 7:0 of lba. */
+	uint8_t lba0;
+	/** bits 15:8 of lba. */
+	uint8_t lba1;
+	/** bits 23:16 of lba. */
+	uint8_t lba2;
+	uint8_t fua;
+	/** bits 31:24 of lba. */
+	uint8_t lba3;
+	/** bits 39:32 of lba. */
+	uint8_t lba4;
+	/** bits 47:40 of lba. */
+	uint8_t lba5;
+	/** bits 15:8 of sector count. */
+	uint8_t sector_count_high;
+	/** Tag number of NCQ operation. */
+	uint8_t tag;
+	/** Reserved. */
+	uint8_t reserved1;
+	/** Reserved. */
+	uint8_t reserved2;
+	/** Control. */
+	uint8_t control;
+	/** Reserved. */
+	uint8_t reserved3;
+	/** Reserved. */
+	uint8_t reserved4;
+	/** Reserved. */
+	uint8_t reserved5;
+	/** Reserved. */
+	uint8_t reserved6;
+} sata_ncq_command_frame_t;
+
+/*----------------------------------------------------------------------------*/
+/*-- SATA Identify device ----------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Data returned from identify device and identify packet device command. */
+typedef struct {
+	uint16_t gen_conf;
+	uint16_t cylinders;
+	uint16_t reserved2;
+	uint16_t heads;
+	uint16_t _vs4;
+	uint16_t _vs5;
+	uint16_t sectors;
+	uint16_t _vs7;
+	uint16_t _vs8;
+	uint16_t _vs9;
+	
+	uint16_t serial_number[10];
+	uint16_t _vs20;
+	uint16_t _vs21;
+	uint16_t vs_bytes;
+	uint16_t firmware_rev[4];
+	uint16_t model_name[20];
+	
+	uint16_t max_rw_multiple;
+	uint16_t reserved48;
+	/* Different meaning for packet device. */
+	uint16_t caps;
+	uint16_t reserved50;
+	uint16_t pio_timing;
+	uint16_t dma_timing;
+	
+	uint16_t validity;
+	uint16_t cur_cyl;
+	uint16_t cur_heads;
+	uint16_t cur_sectors;
+	uint16_t cur_capacity0;
+	uint16_t cur_capacity1;
+	uint16_t mss;
+	uint16_t total_lba28_0;
+	uint16_t total_lba28_1;
+	uint16_t sw_dma;
+	uint16_t mw_dma;
+	uint16_t pio_modes;
+	uint16_t min_mw_dma_cycle;
+	uint16_t rec_mw_dma_cycle;
+	uint16_t min_raw_pio_cycle;
+	uint16_t min_iordy_pio_cycle;
+	
+	uint16_t reserved69;
+	uint16_t reserved70;
+	uint16_t reserved71;
+	uint16_t reserved72;
+	uint16_t reserved73;
+	uint16_t reserved74;
+	
+	uint16_t queue_depth;
+	/** SATA capatibilities - different meaning for packet device. */
+	uint16_t sata_cap;
+	/** SATA additional capatibilities - different meaning for packet device. */
+	uint16_t sata_cap2;
+	uint16_t reserved78[1 + 79 - 78];
+	uint16_t version_maj;
+	uint16_t version_min;
+	uint16_t cmd_set0;
+	uint16_t cmd_set1;
+	uint16_t csf_sup_ext;
+	uint16_t csf_enabled0;
+	uint16_t csf_enabled1;
+	uint16_t csf_default;
+	uint16_t udma;
+	
+	uint16_t reserved89[1 + 99 - 89];
+	
+	/* Total number of blocks in LBA-48 addressing. */
+	uint16_t total_lba48_0;
+	uint16_t total_lba48_1;
+	uint16_t total_lba48_2;
+	uint16_t total_lba48_3;
+	
+	uint16_t reserved104[1 + 105 - 104];
+	uint16_t physical_logic_sector_size;
+	/* Note: more fields are defined in ATA/ATAPI-7. */
+	uint16_t reserved107[1 + 127 - 107];
+	uint16_t reserved128[1 + 159 - 128];
+	uint16_t reserved160[1 + 255 - 160];
+} sata_identify_data_t;
+
+/** Capability bits for register device. */
+enum sata_rd_caps {
+	sata_rd_cap_iordy = 0x0800,
+	sata_rd_cap_iordy_cbd = 0x0400,
+	sata_rd_cap_lba = 0x0200,
+	sata_rd_cap_dma = 0x0100
+};
+
+/** Bits of @c identify_data_t.cmd_set1. */
+enum sata_cs1 {
+	/** 48-bit address feature set. */
+	sata_cs1_addr48 = 0x0400
+};
+
+/** SATA capatibilities for not packet device - Serial ATA revision 3_1. */
+enum sata_np_caps {
+	/** Supports READ LOG DMA EXT. */
+	sata_np_cap_log_ext = 0x8000,
+	/** Supports Device Automatic Partial to Slumber transitions. */
+	sata_np_cap_dev_slm = 0x4000,
+	/** Supports Host Automatic Partial to Slumber transitions. */
+	sata_np_cap_host_slm = 0x2000,
+	/** Supports NCQ priority information. */
+	sata_np_cap_ncq_prio = 0x1000,
+	/** Supports Unload while NCQ command outstanding. */
+	sata_np_cap_unload_ncq = 0x0800,
+	/** Supports Phy event counters. */
+	sata_np_cap_phy_ctx = 0x0400,
+	/** Supports recepits of host-initiated interface power management. */
+	sata_np_cap_host_pmngmnt = 0x0200,
+	
+	/** Supports NCQ. */
+	sata_np_cap_ncq = 0x0100,
+	
+	/** Supports SATA 3. */
+	sata_np_cap_sata_3 = 0x0008,
+	/** Supports SATA 2. */
+	sata_np_cap_sata_2 = 0x0004,
+	/** Supports SATA 1. */
+	sata_np_cap_sata_1 = 0x0002
+};
+
+/** SATA capatibilities for packet device - Serial ATA revision 3_1. */
+enum sata_pt_caps {
+	/** Supports READ LOG DMA EXT. */
+	sata_pt_cap_log_ext = 0x8000,
+	/** Supports Device Automatic Partial to Slumber transitions. */
+	sata_pt_cap_dev_slm = 0x4000,
+	/** Supports Host Automatic Partial to Slumber transitions. */
+	sata_pt_cap_host_slm = 0x2000,
+	/** Supports Phy event counters. */
+	sata_pt_cap_phy_ctx = 0x0400,
+	/** Supports recepits of host-initiated interface power management. */
+	sata_pt_cap_host_pmngmnt = 0x0200,
+	
+	/** Supports SATA 3. */
+	sata_pt_cap_sat_3 = 0x0008,
+	/** Supports SATA 2. */
+	sata_pt_cap_sat_2 = 0x0004,
+	/** Supports SATA 1. */
+	sata_pt_cap_sat_1 = 0x0002
+};
+
+#endif
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/isa/isa.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -201,6 +201,8 @@
 
 	isa_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(isa_fun_t));
-	if (fun == NULL)
+	if (fun == NULL) {
+		ddf_fun_destroy(fnode);
 		return NULL;
+	}
 
 	fibril_mutex_initialize(&fun->mutex);
@@ -552,6 +554,6 @@
 
 	isa_fun_t *fun = isa_fun_create(isa, fun_name);
+	free(fun_name);
 	if (fun == NULL) {
-		free(fun_name);
 		return NULL;
 	}
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -38,4 +38,5 @@
 
 #include <assert.h>
+#include <byteorder.h>
 #include <stdio.h>
 #include <errno.h>
@@ -231,15 +232,16 @@
 	void *addr = bus->conf_data_port + (reg & 3);
 	
-	pio_write_32(bus->conf_addr_port, conf_addr);
+	pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
 	
 	switch (len) {
 	case 1:
+		/* No endianness change for 1 byte */
 		buf[0] = pio_read_8(addr);
 		break;
 	case 2:
-		((uint16_t *) buf)[0] = pio_read_16(addr);
+		((uint16_t *) buf)[0] = uint16_t_le2host(pio_read_16(addr));
 		break;
 	case 4:
-		((uint32_t *) buf)[0] = pio_read_32(addr);
+		((uint32_t *) buf)[0] = uint32_t_le2host(pio_read_32(addr));
 		break;
 	}
@@ -254,19 +256,19 @@
 	fibril_mutex_lock(&bus->conf_mutex);
 	
-	uint32_t conf_addr;
-	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
+	const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
 	void *addr = bus->conf_data_port + (reg & 3);
 	
-	pio_write_32(bus->conf_addr_port, conf_addr);
+	pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
 	
 	switch (len) {
 	case 1:
+		/* No endianness change for 1 byte */
 		pio_write_8(addr, buf[0]);
 		break;
 	case 2:
-		pio_write_16(addr, ((uint16_t *) buf)[0]);
+		pio_write_16(addr, host2uint16_t_le(((uint16_t *) buf)[0]));
 		break;
 	case 4:
-		pio_write_32(addr, ((uint32_t *) buf)[0]);
+		pio_write_32(addr, host2uint32_t_le(((uint32_t *) buf)[0]));
 		break;
 	}
@@ -650,15 +652,23 @@
 	got_res = true;
 	
+	
+	assert(hw_resources.count > 1);
+	assert(hw_resources.resources[0].type == IO_RANGE);
+	assert(hw_resources.resources[0].res.io_range.size >= 4);
+	
+	assert(hw_resources.resources[1].type == IO_RANGE);
+	assert(hw_resources.resources[1].res.io_range.size >= 4);
+	
 	ddf_msg(LVL_DEBUG, "conf_addr = %" PRIx64 ".",
 	    hw_resources.resources[0].res.io_range.address);
-	
-	assert(hw_resources.count > 0);
-	assert(hw_resources.resources[0].type == IO_RANGE);
-	assert(hw_resources.resources[0].res.io_range.size == 8);
+	ddf_msg(LVL_DEBUG, "data_addr = %" PRIx64 ".",
+	    hw_resources.resources[1].res.io_range.address);
 	
 	bus->conf_io_addr =
 	    (uint32_t) hw_resources.resources[0].res.io_range.address;
-	
-	if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 8,
+	bus->conf_io_data =
+	    (uint32_t) hw_resources.resources[1].res.io_range.address;
+	
+	if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 4,
 	    &bus->conf_addr_port)) {
 		ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
@@ -666,5 +676,10 @@
 		goto fail;
 	}
-	bus->conf_data_port = (char *) bus->conf_addr_port + 4;
+	if (pio_enable((void *)(uintptr_t)bus->conf_io_data, 4,
+	    &bus->conf_data_port)) {
+		ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
+		rc = EADDRNOTAVAIL;
+		goto fail;
+	}
 	
 	/* Make the bus device more visible. It has no use yet. */
Index: uspace/drv/bus/pci/pciintel/pci.h
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/pci/pciintel/pci.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -46,4 +46,5 @@
 	ddf_dev_t *dnode;
 	uint32_t conf_io_addr;
+	uint32_t conf_io_data;
 	void *conf_data_port;
 	void *conf_addr_port;
Index: uspace/drv/bus/usb/ehci/main.c
===================================================================
--- uspace/drv/bus/usb/ehci/main.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ehci/main.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -49,9 +49,9 @@
 
 static int ehci_dev_add(ddf_dev_t *device);
-/*----------------------------------------------------------------------------*/
+
 static driver_ops_t ehci_driver_ops = {
 	.dev_add = ehci_dev_add,
 };
-/*----------------------------------------------------------------------------*/
+
 static driver_t ehci_driver = {
 	.name = NAME,
@@ -62,5 +62,5 @@
 };
 
-/*----------------------------------------------------------------------------*/
+
 /** Initializes a new ddf driver instance of EHCI hcd.
  *
@@ -121,5 +121,5 @@
 #undef CHECK_RET_RETURN
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initializes global driver structures (NONE).
  *
Index: uspace/drv/bus/usb/ohci/endpoint_list.c
===================================================================
--- uspace/drv/bus/usb/ohci/endpoint_list.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/endpoint_list.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -65,5 +65,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Set the next list in transfer list chain.
  *
@@ -80,5 +80,5 @@
 	ed_append_ed(instance->list_head, next->list_head);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Add endpoint to the list and queue.
  *
@@ -132,5 +132,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Remove endpoint from the list and queue.
  *
@@ -162,5 +162,5 @@
 		qpos = "NOT FIRST";
 	}
-	assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(ep->ed));
+	assert(ed_next(prev_ed) == addr_to_phys(ep->ed));
 	prev_ed->next = ep->ed->next;
 	/* Make sure ED is updated */
Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -26,4 +26,5 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 /** @addtogroup drvusbohcihc
  * @{
@@ -32,4 +33,5 @@
  * @brief OHCI Host controller driver routines
  */
+
 #include <errno.h>
 #include <str_error.h>
@@ -49,5 +51,5 @@
 static const irq_pio_range_t ohci_pio_ranges[] = {
 	{
-		.base = 0,	/* filled later */
+		.base = 0,
 		.size = sizeof(ohci_regs_t)
 	}
@@ -55,9 +57,28 @@
 
 static const irq_cmd_t ohci_irq_commands[] = {
-	{ .cmd = CMD_PIO_READ_32, .dstarg = 1, .addr = NULL /* filled later */ },
-	{ .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = OHCI_USED_INTERRUPTS },
-	{ .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
-	{ .cmd = CMD_PIO_WRITE_A_32, .srcarg = 1, .addr = NULL /* filled later */ },
-	{ .cmd = CMD_ACCEPT },
+	{
+		.cmd = CMD_PIO_READ_32,
+		.dstarg = 1,
+		.addr = NULL
+	},
+	{
+		.cmd = CMD_AND,
+		.srcarg = 1,
+		.dstarg = 2,
+		.value = 0
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.srcarg = 2,
+		.value = 2
+	},
+	{
+		.cmd = CMD_PIO_WRITE_A_32,
+		.srcarg = 1,
+		.addr = NULL
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
 };
 
@@ -68,5 +89,5 @@
 static int interrupt_emulator(hc_t *instance);
 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
-/*----------------------------------------------------------------------------*/
+
 /** Get number of PIO ranges used in IRQ code.
  * @return Number of ranges.
@@ -76,6 +97,5 @@
 	return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);
 }
-/*----------------------------------------------------------------------------*/
-/*----------------------------------------------------------------------------*/
+
 /** Get number of commands used in IRQ code.
  * @return Number of commands.
@@ -85,5 +105,5 @@
 	return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Generate IRQ code.
  * @param[out] ranges PIO ranges buffer.
@@ -112,8 +132,9 @@
 	cmds[0].addr = (void *) &registers->interrupt_status;
 	cmds[3].addr = (void *) &registers->interrupt_status;
+	OHCI_WR(cmds[1].value, OHCI_USED_INTERRUPTS);
 
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Announce OHCI root hub to the DDF
  *
@@ -174,5 +195,5 @@
 #undef CHECK_RET_RELEASE
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize OHCI hc driver structure
  *
@@ -227,5 +248,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
 {
@@ -241,23 +262,24 @@
 	switch (ep->transfer_type) {
 	case USB_TRANSFER_CONTROL:
-		instance->registers->control &= ~C_CLE;
+		OHCI_CLR(instance->registers->control, C_CLE);
 		endpoint_list_add_ep(list, ohci_ep);
-		instance->registers->control_current = 0;
-		instance->registers->control |= C_CLE;
+		OHCI_WR(instance->registers->control_current, 0);
+		OHCI_SET(instance->registers->control, C_CLE);
 		break;
 	case USB_TRANSFER_BULK:
-		instance->registers->control &= ~C_BLE;
+		OHCI_CLR(instance->registers->control, C_BLE);
 		endpoint_list_add_ep(list, ohci_ep);
-		instance->registers->control |= C_BLE;
+		OHCI_WR(instance->registers->bulk_current, 0);
+		OHCI_SET(instance->registers->control, C_BLE);
 		break;
 	case USB_TRANSFER_ISOCHRONOUS:
 	case USB_TRANSFER_INTERRUPT:
-		instance->registers->control &= (~C_PLE & ~C_IE);
+		OHCI_CLR(instance->registers->control, C_PLE | C_IE);
 		endpoint_list_add_ep(list, ohci_ep);
-		instance->registers->control |= C_PLE | C_IE;
-		break;
-	}
-}
-/*----------------------------------------------------------------------------*/
+		OHCI_SET(instance->registers->control, C_PLE | C_IE);
+		break;
+	}
+}
+
 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep)
 {
@@ -273,19 +295,20 @@
 	switch (ep->transfer_type) {
 	case USB_TRANSFER_CONTROL:
-		instance->registers->control &= ~C_CLE;
+		OHCI_CLR(instance->registers->control, C_CLE);
 		endpoint_list_remove_ep(list, ohci_ep);
-		instance->registers->control_current = 0;
-		instance->registers->control |= C_CLE;
+		OHCI_WR(instance->registers->control_current, 0);
+		OHCI_SET(instance->registers->control, C_CLE);
 		break;
 	case USB_TRANSFER_BULK:
-		instance->registers->control &= ~C_BLE;
+		OHCI_CLR(instance->registers->control, C_BLE);
 		endpoint_list_remove_ep(list, ohci_ep);
-		instance->registers->control |= C_BLE;
+		OHCI_WR(instance->registers->bulk_current, 0);
+		OHCI_SET(instance->registers->control, C_BLE);
 		break;
 	case USB_TRANSFER_ISOCHRONOUS:
 	case USB_TRANSFER_INTERRUPT:
-		instance->registers->control &= (~C_PLE & ~C_IE);
+		OHCI_CLR(instance->registers->control, C_PLE | C_IE);
 		endpoint_list_remove_ep(list, ohci_ep);
-		instance->registers->control |= C_PLE | C_IE;
+		OHCI_SET(instance->registers->control, C_PLE | C_IE);
 		break;
 	default:
@@ -293,5 +316,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Add USB transfer to the schedule.
  *
@@ -308,4 +331,5 @@
 	/* Check for root hub communication */
 	if (batch->ep->address == instance->rh.address) {
+		usb_log_debug("OHCI root hub request.\n");
 		rh_request(&instance->rh, batch);
 		return EOK;
@@ -323,8 +347,8 @@
 	{
 	case USB_TRANSFER_CONTROL:
-		instance->registers->command_status |= CS_CLF;
+		OHCI_SET(instance->registers->command_status, CS_CLF);
 		break;
 	case USB_TRANSFER_BULK:
-		instance->registers->command_status |= CS_BLF;
+		OHCI_SET(instance->registers->command_status, CS_BLF);
 		break;
 	default:
@@ -334,5 +358,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Interrupt handling routine
  *
@@ -342,4 +366,5 @@
 void hc_interrupt(hc_t *instance, uint32_t status)
 {
+	status = OHCI_RD(status);
 	assert(instance);
 	if ((status & ~I_SF) == 0) /* ignore sof status */
@@ -352,8 +377,8 @@
 		fibril_mutex_lock(&instance->guard);
 		usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
-		    instance->registers->hcca,
+		    OHCI_RD(instance->registers->hcca),
 		    (void *) addr_to_phys(instance->hcca));
 		usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
-		    instance->registers->periodic_current);
+		    OHCI_RD(instance->registers->periodic_current));
 
 		link_t *current = list_first(&instance->pending_batches);
@@ -379,5 +404,5 @@
 
 }
-/*----------------------------------------------------------------------------*/
+
 /** Check status register regularly
  *
@@ -397,5 +422,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Turn off any (BIOS)driver that might be in control of the device.
  *
@@ -410,5 +435,5 @@
 
 	usb_log_debug("Requesting OHCI control.\n");
-	if (instance->registers->revision & R_LEGACY_FLAG) {
+	if (OHCI_RD(instance->registers->revision) & R_LEGACY_FLAG) {
 		/* Turn off legacy emulation, it should be enough to zero
 		 * the lowest bit, but it caused problems. Thus clear all
@@ -419,18 +444,18 @@
 		(uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET);
 		usb_log_debug("OHCI legacy register %p: %x.\n",
-		    ohci_emulation_reg, *ohci_emulation_reg);
+		    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
 		/* Zero everything but A20State */
-		*ohci_emulation_reg &= 0x100;
+		OHCI_CLR(*ohci_emulation_reg, ~0x100);
 		usb_log_debug(
 		    "OHCI legacy register (should be 0 or 0x100) %p: %x.\n",
-		    ohci_emulation_reg, *ohci_emulation_reg);
+		    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
 	}
 
 	/* Interrupt routing enabled => smm driver is active */
-	if (instance->registers->control & C_IR) {
+	if (OHCI_RD(instance->registers->control) & C_IR) {
 		usb_log_debug("SMM driver: request ownership change.\n");
-		instance->registers->command_status |= CS_OCR;
+		OHCI_SET(instance->registers->command_status, CS_OCR);
 		/* Hope that SMM actually knows its stuff or we can hang here */
-		while (instance->registers->control & C_IR) {
+		while (OHCI_RD(instance->registers->control & C_IR)) {
 			async_usleep(1000);
 		}
@@ -449,5 +474,5 @@
 			return;
 		}
-		/* HC is suspended assert resume for 20ms, */
+		/* HC is suspended assert resume for 20ms */
 		C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
 		async_usleep(20000);
@@ -461,5 +486,5 @@
 	async_usleep(50000);
 }
-/*----------------------------------------------------------------------------*/
+
 /** OHCI hw initialization routine.
  *
@@ -473,5 +498,5 @@
 
 	/* Save contents of fm_interval register */
-	const uint32_t fm_interval = instance->registers->fm_interval;
+	const uint32_t fm_interval = OHCI_RD(instance->registers->fm_interval);
 	usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
 
@@ -479,6 +504,6 @@
 	usb_log_debug2("HC reset.\n");
 	size_t time = 0;
-	instance->registers->command_status = CS_HCR;
-	while (instance->registers->command_status & CS_HCR) {
+	OHCI_WR(instance->registers->command_status, CS_HCR);
+	while (OHCI_RD(instance->registers->command_status) & CS_HCR) {
 		async_usleep(10);
 		time += 10;
@@ -487,23 +512,23 @@
 
 	/* Restore fm_interval */
-	instance->registers->fm_interval = fm_interval;
-	assert((instance->registers->command_status & CS_HCR) == 0);
+	OHCI_WR(instance->registers->fm_interval, fm_interval);
+	assert((OHCI_RD(instance->registers->command_status) & CS_HCR) == 0);
 
 	/* hc is now in suspend state */
 	usb_log_debug2("HC should be in suspend state(%x).\n",
-	    instance->registers->control);
+	    OHCI_RD(instance->registers->control));
 
 	/* Use HCCA */
-	instance->registers->hcca = addr_to_phys(instance->hcca);
+	OHCI_WR(instance->registers->hcca, addr_to_phys(instance->hcca));
 
 	/* Use queues */
-	instance->registers->bulk_head =
-	    instance->lists[USB_TRANSFER_BULK].list_head_pa;
+	OHCI_WR(instance->registers->bulk_head,
+	    instance->lists[USB_TRANSFER_BULK].list_head_pa);
 	usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
 	    instance->lists[USB_TRANSFER_BULK].list_head,
 	    instance->lists[USB_TRANSFER_BULK].list_head_pa);
 
-	instance->registers->control_head =
-	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
+	OHCI_WR(instance->registers->control_head,
+	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
 	usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
 	    instance->lists[USB_TRANSFER_CONTROL].list_head,
@@ -511,26 +536,27 @@
 
 	/* Enable queues */
-	instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
-	usb_log_debug2("All queues enabled(%x).\n",
-	    instance->registers->control);
+	OHCI_SET(instance->registers->control, (C_PLE | C_IE | C_CLE | C_BLE));
+	usb_log_debug("Queues enabled(%x).\n",
+	    OHCI_RD(instance->registers->control));
 
 	/* Enable interrupts */
-	instance->registers->interrupt_enable = OHCI_USED_INTERRUPTS;
-	usb_log_debug2("Enabled interrupts: %x.\n",
-	    instance->registers->interrupt_enable);
-	instance->registers->interrupt_enable = I_MI;
+	OHCI_WR(instance->registers->interrupt_enable, OHCI_USED_INTERRUPTS);
+	usb_log_debug("Enabled interrupts: %x.\n",
+	    OHCI_RD(instance->registers->interrupt_enable));
+	OHCI_WR(instance->registers->interrupt_enable, I_MI);
 
 	/* Set periodic start to 90% */
-	uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
-	instance->registers->periodic_start = (frame_length / 10) * 9;
+	const uint32_t frame_length =
+	    (fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK;
+	OHCI_WR(instance->registers->periodic_start,
+	    ((frame_length / 10) * 9) & PS_MASK << PS_SHIFT);
 	usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
-	    instance->registers->periodic_start,
-	    instance->registers->periodic_start, frame_length);
-
+	    OHCI_RD(instance->registers->periodic_start),
+	    OHCI_RD(instance->registers->periodic_start), frame_length);
 	C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);
 	usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
-	    instance->registers->control);
-}
-/*----------------------------------------------------------------------------*/
+	    OHCI_RD(instance->registers->control));
+}
+
 /** Initialize schedule queues
  *
@@ -566,5 +592,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize memory structures used by the OHCI hcd.
  *
@@ -587,10 +613,9 @@
 	if (instance->hcca == NULL)
 		return ENOMEM;
-	bzero(instance->hcca, sizeof(hcca_t));
 	usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
 
-	for (unsigned i = 0; i < 32; ++i) {
-		instance->hcca->int_ep[i] =
-		    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
+	for (unsigned i = 0; i < HCCA_INT_EP_COUNT; ++i) {
+		hcca_set_int_ep(instance->hcca, i,
+		    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
 	}
 	usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
Index: uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -58,5 +58,5 @@
 		/* Mark as dead, used for dummy EDs at the beginning of
 		 * endpoint lists. */
-		instance->status = ED_STATUS_K_FLAG;
+		OHCI_MEM32_WR(instance->status, ED_STATUS_K_FLAG);
 		return;
 	}
@@ -65,27 +65,27 @@
 
 	/* Status: address, endpoint nr, direction mask and max packet size. */
-	instance->status = 0
-	    | ((ep->address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT)
+	OHCI_MEM32_WR(instance->status,
+	    ((ep->address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT)
 	    | ((ep->endpoint & ED_STATUS_EN_MASK) << ED_STATUS_EN_SHIFT)
 	    | ((dir[ep->direction] & ED_STATUS_D_MASK) << ED_STATUS_D_SHIFT)
 	    | ((ep->max_packet_size & ED_STATUS_MPS_MASK)
-	        << ED_STATUS_MPS_SHIFT);
+	        << ED_STATUS_MPS_SHIFT));
 
 	/* Low speed flag */
 	if (ep->speed == USB_SPEED_LOW)
-		instance->status |= ED_STATUS_S_FLAG;
+		OHCI_MEM32_SET(instance->status, ED_STATUS_S_FLAG);
 
 	/* Isochronous format flag */
 	if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS)
-		instance->status |= ED_STATUS_F_FLAG;
+		OHCI_MEM32_SET(instance->status, ED_STATUS_F_FLAG);
 
 	/* Set TD to the list */
 	const uintptr_t pa = addr_to_phys(td);
-	instance->td_head = pa & ED_TDHEAD_PTR_MASK;
-	instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
+	OHCI_MEM32_WR(instance->td_head, pa & ED_TDHEAD_PTR_MASK);
+	OHCI_MEM32_WR(instance->td_tail, pa & ED_TDTAIL_PTR_MASK);
 
 	/* Set toggle bit */
 	if (ep->toggle)
-		instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
+		OHCI_MEM32_SET(instance->td_head, ED_TDHEAD_TOGGLE_CARRY);
 
 }
Index: uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -44,4 +44,5 @@
 
 #include "completion_codes.h"
+#include "mem_access.h"
 
 /**
@@ -116,6 +117,12 @@
 {
 	assert(instance);
-	return (instance->td_head & ED_TDHEAD_HALTED_FLAG)
-	    || (instance->status & ED_STATUS_K_FLAG);
+	return (OHCI_MEM32_RD(instance->td_head) & ED_TDHEAD_HALTED_FLAG)
+	    || (OHCI_MEM32_RD(instance->status) & ED_STATUS_K_FLAG);
+}
+
+static inline void ed_clear_halt(ed_t *instance)
+{
+	assert(instance);
+	OHCI_MEM32_CLR(instance->td_head, ED_TDHEAD_HALTED_FLAG);
 }
 
@@ -128,6 +135,6 @@
 {
 	assert(instance);
-	return (instance->td_head & ED_TDHEAD_PTR_MASK)
-	    != (instance->td_tail & ED_TDTAIL_PTR_MASK);
+	return (OHCI_MEM32_RD(instance->td_head) & ED_TDHEAD_PTR_MASK)
+	    != (OHCI_MEM32_RD(instance->td_tail) & ED_TDTAIL_PTR_MASK);
 }
 
@@ -141,5 +148,17 @@
 	assert(instance);
 	const uintptr_t pa = addr_to_phys(td);
-	instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
+	OHCI_MEM32_WR(instance->td_tail, pa & ED_TDTAIL_PTR_MASK);
+}
+
+static inline uint32_t ed_tail_td(const ed_t *instance)
+{
+	assert(instance);
+	return OHCI_MEM32_RD(instance->td_tail) & ED_TDTAIL_PTR_MASK;
+}
+
+static inline uint32_t ed_head_td(const ed_t *instance)
+{
+	assert(instance);
+	return OHCI_MEM32_RD(instance->td_head) & ED_TDHEAD_PTR_MASK;
 }
 
@@ -155,5 +174,11 @@
 	const uint32_t pa = addr_to_phys(next);
 	assert((pa & ED_NEXT_PTR_MASK) << ED_NEXT_PTR_SHIFT == pa);
-	instance->next = pa;
+	OHCI_MEM32_WR(instance->next, pa);
+}
+
+static inline uint32_t ed_next(const ed_t *instance)
+{
+	assert(instance);
+	return OHCI_MEM32_RD(instance->next) & ED_NEXT_PTR_MASK;
 }
 
@@ -166,5 +191,5 @@
 {
 	assert(instance);
-	return (instance->td_head & ED_TDHEAD_TOGGLE_CARRY) ? 1 : 0;
+	return (OHCI_MEM32_RD(instance->td_head) & ED_TDHEAD_TOGGLE_CARRY) ? 1 : 0;
 }
 
@@ -178,9 +203,9 @@
 	assert(instance);
 	if (toggle) {
-		instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
+		OHCI_MEM32_SET(instance->td_head, ED_TDHEAD_TOGGLE_CARRY);
 	} else {
 		/* Clear halted flag when reseting toggle TODO: Why? */
-		instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY;
-		instance->td_head &= ~ED_TDHEAD_HALTED_FLAG;
+		OHCI_MEM32_CLR(instance->td_head, ED_TDHEAD_TOGGLE_CARRY);
+		OHCI_MEM32_CLR(instance->td_head, ED_TDHEAD_HALTED_FLAG);
 	}
 }
Index: uspace/drv/bus/usb/ohci/hw_struct/hcca.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/hcca.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/hw_struct/hcca.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -38,19 +38,49 @@
 #include <malloc.h>
 
+#include "mem_access.h"
+
+#define HCCA_INT_EP_COUNT  32
+
 /** Host controller communication area.
  * Shared memory used for communication between the controller and the driver.
  */
 typedef struct hcca {
-	uint32_t int_ep[32];
+	/** Interrupt endpoints */
+	uint32_t int_ep[HCCA_INT_EP_COUNT];
+	/** Frame number. */
 	uint16_t frame_number;
 	uint16_t pad1;
+	/** Pointer to the last completed TD. (useless) */
 	uint32_t done_head;
+	/** Padding to make the size 256B */
 	uint32_t reserved[30];
 } hcca_t;
 
-static inline void * hcca_get(void)
+/** Allocate properly aligned structure.
+ *
+ * The returned structure is zeroed upon allocation.
+ *
+ * @return Usable HCCA memory structure.
+ */
+static inline hcca_t * hcca_get(void)
 {
 	assert(sizeof(hcca_t) == 256);
-	return memalign(256, sizeof(hcca_t));
+	hcca_t *hcca = memalign(256, sizeof(hcca_t));
+	if (hcca)
+		bzero(hcca, sizeof(hcca_t));
+	return hcca;
+}
+
+/** Set HCCA interrupt endpoint pointer table entry.
+ * @param hcca HCCA memory structure.
+ * @param index table index.
+ * @param pa Physical address.
+ */
+static inline void hcca_set_int_ep(hcca_t *hcca, unsigned index, uintptr_t pa)
+{
+	assert(hcca);
+	assert(index < HCCA_INT_EP_COUNT);
+	OHCI_MEM32_WR(hcca->int_ep[index], pa);
+
 }
 #endif
Index: uspace/drv/bus/usb/ohci/hw_struct/mem_access.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/mem_access.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/drv/bus/usb/ohci/hw_struct/mem_access.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HW_MEM_ACCESS_H
+#define DRV_OHCI_HW_MEM_ACCESS_H
+
+#include <byteorder.h>
+
+#define OHCI_MEM32_WR(reg, val) reg = host2uint32_t_le(val)
+#define OHCI_MEM32_RD(reg) uint32_t_le2host(reg)
+#define OHCI_MEM32_SET(reg, val) reg |= host2uint32_t_le(val)
+#define OHCI_MEM32_CLR(reg, val) reg &= host2uint32_t_le(~val)
+
+#endif
+
+/*
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -33,4 +33,6 @@
  */
 #include <usb/usb.h>
+#include <mem.h>
+#include "../utils/malloc32.h"
 #include "transfer_descriptor.h"
 
@@ -58,26 +60,26 @@
 	bzero(instance, sizeof(td_t));
 	/* Set PID and Error code */
-	instance->status = 0
-	    | ((dir[direction] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)
-	    | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT);
+	OHCI_MEM32_WR(instance->status,
+	    ((dir[direction] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)
+	    | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT));
 
 	if (toggle == 0 || toggle == 1) {
 		/* Set explicit toggle bit */
-		instance->status |= TD_STATUS_T_USE_TD_FLAG;
-		instance->status |= toggle ? TD_STATUS_T_FLAG : 0;
+		OHCI_MEM32_SET(instance->status, TD_STATUS_T_USE_TD_FLAG);
+		OHCI_MEM32_SET(instance->status, toggle ? TD_STATUS_T_FLAG : 0);
 	}
 
 	/* Alow less data on input. */
 	if (dir == USB_DIRECTION_IN) {
-		instance->status |= TD_STATUS_ROUND_FLAG;
+		OHCI_MEM32_SET(instance->status, TD_STATUS_ROUND_FLAG);
 	}
 
 	if (buffer != NULL) {
 		assert(size != 0);
-		instance->cbp = addr_to_phys(buffer);
-		instance->be = addr_to_phys(buffer + size - 1);
+		OHCI_MEM32_WR(instance->cbp, addr_to_phys(buffer));
+		OHCI_MEM32_WR(instance->be, addr_to_phys(buffer + size - 1));
 	}
 
-	instance->next = addr_to_phys(next) & TD_NEXT_PTR_MASK;
+	OHCI_MEM32_WR(instance->next, addr_to_phys(next) & TD_NEXT_PTR_MASK);
 
 }
Index: uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -38,5 +38,5 @@
 #include <stdint.h>
 
-#include "../utils/malloc32.h"
+#include "mem_access.h"
 #include "completion_codes.h"
 
@@ -100,6 +100,6 @@
 {
 	assert(instance);
-	const int cc =
-	    (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
+	const int cc =(OHCI_MEM32_RD(instance->status)
+	    >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
 	/* This value is changed on transfer completion,
 	 * either to CC_NOERROR or and error code.
@@ -119,6 +119,6 @@
 {
 	assert(instance);
-	const int cc =
-	    (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
+	const int cc = (OHCI_MEM32_RD(instance->status)
+	    >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
 	return cc_to_rc(cc);
 }
@@ -136,5 +136,5 @@
 		return 0;
 	/* Buffer end points to the last byte of transfer buffer, so add 1 */
-	return instance->be - instance->cbp + 1;
+	return OHCI_MEM32_RD(instance->be) - OHCI_MEM32_RD(instance->cbp) + 1;
 }
 #endif
Index: uspace/drv/bus/usb/ohci/main.c
===================================================================
--- uspace/drv/bus/usb/ohci/main.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/main.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -63,14 +63,14 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static driver_ops_t ohci_driver_ops = {
 	.dev_add = ohci_dev_add,
 };
-/*----------------------------------------------------------------------------*/
+
 static driver_t ohci_driver = {
 	.name = NAME,
 	.driver_ops = &ohci_driver_ops
 };
-/*----------------------------------------------------------------------------*/
+
 /** Initializes global driver structures (NONE).
  *
Index: uspace/drv/bus/usb/ohci/ohci.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -75,5 +75,5 @@
 	hc_interrupt(&ohci->hc, status);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Get USB address assigned to root hub.
  *
@@ -92,5 +92,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Gets handle of the respective hc (this device, hc function).
  *
@@ -110,5 +110,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Root hub USB interface */
 static usb_iface_t usb_iface = {
@@ -116,15 +116,15 @@
 	.get_my_address = rh_get_my_address,
 };
-/*----------------------------------------------------------------------------*/
+
 /** Standard USB HC options (HC interface) */
 static ddf_dev_ops_t hc_ops = {
 	.interfaces[USBHC_DEV_IFACE] = &hcd_iface,
 };
-/*----------------------------------------------------------------------------*/
+
 /** Standard USB RH options (RH interface) */
 static ddf_dev_ops_t rh_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface,
 };
-/*----------------------------------------------------------------------------*/
+
 /** Initialize hc and rh ddf structures and their respective drivers.
  *
Index: uspace/drv/bus/usb/ohci/ohci_batch.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_batch.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/ohci_batch.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -44,5 +44,5 @@
 
 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t);
-/*----------------------------------------------------------------------------*/
+
 /** Safely destructs ohci_transfer_batch_t structure
  *
@@ -67,5 +67,5 @@
 	free(ohci_batch);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Finishes usb_transfer_batch and destroys the structure.
  *
@@ -80,5 +80,5 @@
 	ohci_transfer_batch_dispose(ohci_batch);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Allocate memory and initialize internal data structure.
  *
@@ -158,5 +158,5 @@
 #undef CHECK_NULL_DISPOSE_RET
 }
-/*----------------------------------------------------------------------------*/
+
 /** Check batch TDs' status.
  *
@@ -199,20 +199,21 @@
 		    ohci_batch->tds[i]->next, ohci_batch->tds[i]->be);
 
-		/* If the TD got all its data through, it will report 0 bytes
-		 * remain, the sole exception is INPUT with data rounding flag
-		 * (short), i.e. every INPUT. Nice thing is that short packets
-		 * will correctly report remaining data, thus making
-		 * this computation correct (short packets need to be produced
-		 * by the last TD)
-		 * NOTE: This also works for CONTROL transfer as
-		 * the first TD will return 0 remain.
-		 * NOTE: Short packets don't break the assumption that
-		 * we leave the very last(unused) TD behind.
-		 */
-		ohci_batch->usb_batch->transfered_size
-		    -= td_remain_size(ohci_batch->tds[i]);
-
 		ohci_batch->usb_batch->error = td_error(ohci_batch->tds[i]);
-		if (ohci_batch->usb_batch->error != EOK) {
+		if (ohci_batch->usb_batch->error == EOK) {
+			/* If the TD got all its data through, it will report
+			 * 0 bytes remain, the sole exception is INPUT with
+			 * data rounding flag (short), i.e. every INPUT.
+			 * Nice thing is that short packets will correctly
+			 * report remaining data, thus making this computation
+			 * correct (short packets need to be produced by the
+			 * last TD)
+			 * NOTE: This also works for CONTROL transfer as
+			 * the first TD will return 0 remain.
+			 * NOTE: Short packets don't break the assumption that
+			 * we leave the very last(unused) TD behind.
+			 */
+			ohci_batch->usb_batch->transfered_size
+			    -= td_remain_size(ohci_batch->tds[i]);
+		} else {
 			usb_log_debug("Batch %p found error TD(%zu):%08x.\n",
 			    ohci_batch->usb_batch, i,
@@ -231,14 +232,13 @@
 
 			/* Check TD assumption */
-			const uint32_t pa =
-			    addr_to_phys(ohci_batch->tds[leave_td]);
-			assert((ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK)
-			    == pa);
-
+			assert(ed_head_td(ohci_batch->ed) ==
+			    addr_to_phys(ohci_batch->tds[leave_td]));
+
+			/* Set tail to the same TD */
 			ed_set_tail_td(ohci_batch->ed,
 			    ohci_batch->tds[leave_td]);
 
 			/* Clear possible ED HALT */
-			ohci_batch->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
+			ed_clear_halt(ohci_batch->ed);
 			break;
 		}
@@ -253,11 +253,10 @@
 
 	/* Make sure that we are leaving the right TD behind */
-	const uint32_t pa = addr_to_phys(ohci_ep->td);
-	assert(pa == (ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK));
-	assert(pa == (ohci_batch->ed->td_tail & ED_TDTAIL_PTR_MASK));
+	assert(addr_to_phys(ohci_ep->td) == ed_head_td(ohci_batch->ed));
+	assert(addr_to_phys(ohci_ep->td) == ed_tail_td(ohci_batch->ed));
 
 	return true;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Starts execution of the TD list
  *
@@ -269,5 +268,5 @@
 	ed_set_tail_td(ohci_batch->ed, ohci_batch->tds[ohci_batch->td_count]);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Prepare generic control transfer
  *
@@ -345,5 +344,5 @@
 	    USB_TRANSFER_BATCH_ARGS(*ohci_batch->usb_batch));
 }
-/*----------------------------------------------------------------------------*/
+
 /** Prepare generic data transfer
  *
@@ -392,5 +391,5 @@
 	    USB_TRANSFER_BATCH_ARGS(*ohci_batch->usb_batch));
 }
-/*----------------------------------------------------------------------------*/
+
 /** 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 bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/ohci_batch.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -63,5 +63,5 @@
 void ohci_transfer_batch_commit(const ohci_transfer_batch_t *batch);
 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch);
-/*----------------------------------------------------------------------------*/
+
 static inline ohci_transfer_batch_t *ohci_transfer_batch_from_link(link_t *l)
 {
Index: uspace/drv/bus/usb/ohci/ohci_endpoint.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_endpoint.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/ohci_endpoint.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -48,5 +48,5 @@
 	ed_toggle_set(instance->ed, toggle);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback to get value of toggle bit.
  *
@@ -61,5 +61,5 @@
 	return ed_toggle_get(instance->ed);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Creates new hcd endpoint representation.
  *
@@ -93,5 +93,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Disposes hcd endpoint structure
  *
Index: uspace/drv/bus/usb/ohci/ohci_regs.h
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_regs.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/ohci_regs.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -35,4 +35,11 @@
 #define DRV_OHCI_OHCI_REGS_H
 #include <sys/types.h>
+#include <byteorder.h>
+
+#define OHCI_WR(reg, val) reg = host2uint32_t_le(val)
+#define OHCI_RD(reg) uint32_t_le2host(reg)
+#define OHCI_SET(reg, val) reg |= host2uint32_t_le(val)
+#define OHCI_CLR(reg, val) reg &= host2uint32_t_le(~val)
+
 
 #define LEGACY_REGS_OFFSET 0x100
@@ -42,14 +49,14 @@
 	const ioport32_t revision;
 #define R_REVISION_MASK (0x3f)
-#define R_REVISION_SHIFT (0)
 #define R_LEGACY_FLAG   (0x80)
 
 	ioport32_t control;
-#define C_CBSR_MASK (0x3) /* Control-bulk service ratio */
+/* Control-bulk service ratio */
 #define C_CBSR_1_1  (0x0)
 #define C_CBSR_1_2  (0x1)
 #define C_CBSR_1_3  (0x2)
 #define C_CBSR_1_4  (0x3)
-#define C_CBSR_SHIFT (0)
+#define C_CBSR_MASK (0x3)
+#define C_CBSR_SHIFT 0
 
 #define C_PLE (1 << 2)   /* Periodic list enable */
@@ -58,22 +65,20 @@
 #define C_BLE (1 << 5)   /* Bulk list enable */
 
-#define C_HCFS_MASK        (0x3) /* Host controller functional state */
+/* Host controller functional state */
 #define C_HCFS_RESET       (0x0)
 #define C_HCFS_RESUME      (0x1)
 #define C_HCFS_OPERATIONAL (0x2)
 #define C_HCFS_SUSPEND     (0x3)
-#define C_HCFS_SHIFT       (6)
-
-#define C_HCFS_GET(reg) \
-	((reg >> C_HCFS_SHIFT) & C_HCFS_MASK)
-#define C_HCFS_SET(reg, hcfs_state) \
+#define C_HCFS_GET(reg) ((OHCI_RD(reg) >> 6) & 0x3)
+#define C_HCFS_SET(reg, value) \
 do { \
-	reg = (reg & ~(C_HCFS_MASK << C_HCFS_SHIFT)) \
-	    | ((hcfs_state & C_HCFS_MASK) << C_HCFS_SHIFT); \
+	uint32_t r = OHCI_RD(reg); \
+	r &= ~(0x3 << 6); \
+	r |= (value & 0x3) << 6; \
+	OHCI_WR(reg, r); \
 } while (0)
 
-
-#define C_IR  (1 << 8)   /* Interrupt routing, make sure it's 0 */
-#define C_RWC (1 << 9)   /* Remote wakeup connected, host specific */
+#define C_IR  (1 << 8)  /* Interrupt routing, make sure it's 0 */
+#define C_RWC (1 << 9)  /* Remote wakeup connected, host specific */
 #define C_RWE (1 << 10)  /* Remote wakeup enable */
 
@@ -83,6 +88,8 @@
 #define CS_BLF (1 << 2)   /* Bulk list filled */
 #define CS_OCR (1 << 3)   /* Ownership change request */
+#if 0
 #define CS_SOC_MASK (0x3) /* Scheduling overrun count */
 #define CS_SOC_SHIFT (16)
+#endif
 
 	/** Interupt enable/disable/status,
@@ -101,5 +108,5 @@
 #define I_RHSC (1 << 6)   /* Root hub status change */
 #define I_OC   (1 << 30)  /* Ownership change */
-#define I_MI   (1 << 31)  /* Master interrupt (all/any interrupts) */
+#define I_MI   (1 << 31)  /* Master interrupt (any/all) */
 
 	/** HCCA pointer (see hw_struct hcca.h) */
@@ -145,5 +152,6 @@
 	/** Remaining bit time in frame to start periodic transfers */
 	ioport32_t periodic_start;
-#define PS_PS_MASK (0x3fff) /* bit time when periodic get priority (0x3e67) */
+#define PS_MASK 0x3fff
+#define PS_SHIFT 0
 
 	/** Threshold for starting LS transaction */
@@ -153,46 +161,54 @@
 	/** The first root hub control register */
 	ioport32_t rh_desc_a;
-#define RHDA_NDS_MASK (0xff) /* Number of downstream ports, max 15 */
-#define RHDA_NDS_SHIFT (0)
-#define RHDA_PSM_FLAG  (1 << 8)  /* Power switching mode: 0-global, 1-per port*/
-#define RHDA_NPS_FLAG  (1 << 9)  /* No power switch: 1-power on, 0-use PSM*/
-#define RHDA_DT_FLAG   (1 << 10) /* 1-Compound device, must be 0 */
-#define RHDA_OCPM_FLAG (1 << 11) /* Over-current mode: 0-global, 1-per port */
-#define RHDA_NOCP_FLAG (1 << 12) /* OC control: 0-use OCPM, 1-OC off */
-#define RHDA_POTPGT_MASK (0xff)  /* Power on to power good time */
-#define RHDA_POTPGT_SHIFT (24)
+/** Number of downstream ports, max 15 */
+#define RHDA_NDS_MASK  (0xff)
+/** Power switching mode: 0-global, 1-per port*/
+#define RHDA_PSM_FLAG  (1 << 8)
+/** No power switch: 1-power on, 0-use PSM*/
+#define RHDA_NPS_FLAG  (1 << 9)
+/** 1-Compound device, must be 0 */
+#define RHDA_DT_FLAG   (1 << 10)
+/** Over-current mode: 0-global, 1-per port */
+#define RHDA_OCPM_FLAG (1 << 11)
+/** OC control: 0-use OCPM, 1-OC off */
+#define RHDA_NOCP_FLAG (1 << 12)
+/** Power on to power good time */
+#define RHDA_POTPGT_SHIFT   24
 
 	/** The other root hub control register */
 	ioport32_t rh_desc_b;
-#define RHDB_DR_MASK (0xffff) /* Device removable mask */
-#define RHDB_DR_SHIFT (0)
-#define RHDB_PCC_MASK (0xffff) /* Power control mask */
-#define RHDB_PCC_SHIFT (16)
-
-/* Port device removable status */
-#define RHDB_DR_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)
-/* Port power control status: 1-per port power control, 0-global power switch */
-#define RHDB_PPC_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)
+/** Device removable mask */
+#define RHDB_DR_SHIFT   0
+#define RHDB_DR_MASK    0xffff
+/** Power control mask */
+#define RHDB_PCC_MASK (0xffff)
+#define RHDB_PCC_SHIFT 16
 
 	/** Root hub status register */
 	ioport32_t rh_status;
-#define RHS_LPS_FLAG  (1 <<  0)/* read: 0,
-                                * write: 0-no effect,
-                                *        1-turn off port power for ports
-                                *        specified in PPCM(RHDB), or all ports,
-                                *        if power is set globally */
+/* read: 0,
+ * write: 0-no effect,
+ *        1-turn off port power for ports
+ *        specified in PPCM(RHDB), or all ports,
+ *        if power is set globally */
+#define RHS_LPS_FLAG  (1 <<  0)
 #define RHS_CLEAR_GLOBAL_POWER RHS_LPS_FLAG /* synonym for the above */
-#define RHS_OCI_FLAG  (1 <<  1)/* Over-current indicator, if per-port: 0 */
-#define RHS_DRWE_FLAG (1 << 15)/* read: 0-connect status change does not wake HC
-                                *       1-connect status change wakes HC
-                                * write: 1-set DRWE, 0-no effect */
+/** Over-current indicator, if per-port: 0 */
+#define RHS_OCI_FLAG  (1 <<  1)
+
+/* read: 0-connect status change does not wake HC
+ *       1-connect status change wakes HC
+ * write: 1-set DRWE, 0-no effect */
+#define RHS_DRWE_FLAG (1 << 15)
 #define RHS_SET_DRWE RHS_DRWE_FLAG
-#define RHS_LPSC_FLAG (1 << 16)/* read: 0,
-                                * write: 0-no effect
-                                *        1-turn on port power for ports
-                                *        specified in PPCM(RHDB), or all ports,
-                                *        if power is set globally */
+/* read: 0,
+ * write: 0-no effect
+ *        1-turn on port power for ports
+ *        specified in PPCM(RHDB), or all ports,
+ *        if power is set globally */
+#define RHS_LPSC_FLAG (1 << 16)
 #define RHS_SET_GLOBAL_POWER RHS_LPSC_FLAG /* synonym for the above */
-#define RHS_OCIC_FLAG (1 << 17)/* Over-current indicator change   */
+/** Over-current change indicator*/
+#define RHS_OCIC_FLAG (1 << 17)
 #define RHS_CLEAR_DRWE (1 << 31)
 
@@ -200,32 +216,33 @@
 	ioport32_t rh_port_status[];
 #define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,
-                                * w: 1-clear port enable, 0-nothing */
+                                               * w: 1-clear port enable, 0-N/S*/
 #define RHPS_CLEAR_PORT_ENABLE RHPS_CCS_FLAG
 #define RHPS_PES_FLAG (1 << 1) /* r: port enable status
-                                * w: 1-set port enable, 0-nothing */
+                                              * w: 1-set port enable, 0-N/S */
 #define RHPS_SET_PORT_ENABLE RHPS_PES_FLAG
 #define RHPS_PSS_FLAG (1 << 2) /* r: port suspend status
-                                * w: 1-set port suspend, 0-nothing */
+                                               * w: 1-set port suspend, 0-N/S */
 #define RHPS_SET_PORT_SUSPEND RHPS_PSS_FLAG
-#define RHPS_POCI_FLAG (1 << 3) /* r: port over-current (if reports are per-port
-                                 * w: 1-clear port suspend (start resume
-                                 *      if suspened)
-                                 *    0-nothing */
+#define RHPS_POCI_FLAG (1 << 3) /* r: port over-current
+                                                * (if reports are per-port
+                                                * w: 1-clear port suspend
+						*  (start resume if suspened)
+                                                *    0-nothing */
 #define RHPS_CLEAR_PORT_SUSPEND RHPS_POCI_FLAG
 #define RHPS_PRS_FLAG (1 << 4) /* r: port reset status
-                                * w: 1-set port reset, 0-nothing */
+                                               * w: 1-set port reset, 0-N/S */
 #define RHPS_SET_PORT_RESET RHPS_PRS_FLAG
 #define RHPS_PPS_FLAG (1 << 8) /* r: port power status
-                                * w: 1-set port power, 0-nothing */
+                                              * w: 1-set port power, 0-N/S */
 #define RHPS_SET_PORT_POWER RHPS_PPS_FLAG
 #define RHPS_LSDA_FLAG (1 << 9) /* r: low speed device attached
-                                 * w: 1-clear port power, 0-nothing */
+                                                * w: 1-clear port power, 0-N/S*/
 #define RHPS_CLEAR_PORT_POWER RHPS_LSDA_FLAG
-#define RHPS_CSC_FLAG  (1 << 16) /* connect status change Write-Clean */
+#define RHPS_CSC_FLAG  (1 << 16) /* connect status change WC */
 #define RHPS_PESC_FLAG (1 << 17) /* port enable status change WC */
 #define RHPS_PSSC_FLAG (1 << 18) /* port suspend status change WC */
 #define RHPS_OCIC_FLAG (1 << 19) /* port over-current change WC */
 #define RHPS_PRSC_FLAG (1 << 20) /* port reset status change WC */
-#define RHPS_CHANGE_WC_MASK 0x1f0000
+#define RHPS_CHANGE_WC_MASK (0x1f0000)
 } __attribute__((packed)) ohci_regs_t;
 #endif
Index: uspace/drv/bus/usb/ohci/root_hub.c
===================================================================
--- uspace/drv/bus/usb/ohci/root_hub.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/root_hub.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -33,17 +33,19 @@
  */
 #include <assert.h>
+#include <byteorder.h>
 #include <errno.h>
 #include <str_error.h>
 #include <fibril_synch.h>
 
+#include <usb/usb.h>
 #include <usb/debug.h>
 #include <usb/dev/request.h>
 #include <usb/classes/hub.h>
 
-#include "root_hub.h"
 #include <usb/classes/classes.h>
 #include <usb/classes/hub.h>
 #include <usb/dev/driver.h>
 #include "ohci_regs.h"
+#include "root_hub.h"
 
 /**
@@ -122,4 +124,6 @@
 {
 	assert(request);
+	usb_log_debug("Sending interrupt vector(%zu) %hhx:%hhx.\n",
+	    size, ((uint8_t*)&mask)[0], ((uint8_t*)&mask)[1]);
 	usb_transfer_batch_finish_error(request, &mask, size, EOK);
 	usb_transfer_batch_destroy(request);
@@ -150,6 +154,6 @@
 
 	instance->registers = regs;
-	instance->port_count =
-	    (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
+	instance->port_count = OHCI_RD(regs->rh_desc_a) & RHDA_NDS_MASK;
+	usb_log_debug2("rh_desc_a: %x.\n", OHCI_RD(regs->rh_desc_a));
 	if (instance->port_count > 15) {
 		usb_log_warning("OHCI specification does not allow more than 15"
@@ -163,35 +167,39 @@
 
 #if defined OHCI_POWER_SWITCH_no
+	usb_log_debug("OHCI rh: Set power mode to no power switching.\n");
 	/* Set port power mode to no power-switching. (always on) */
-	instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
+	OHCI_SET(regs->rh_desc_a, RHDA_NPS_FLAG);
 
 	/* Set to no over-current reporting */
-	instance->registers->rh_desc_a |= RHDA_NOCP_FLAG;
+	OHCI_SET(regs->rh_desc_a, RHDA_NOCP_FLAG);
 
 #elif defined OHCI_POWER_SWITCH_ganged
-	/* Set port power mode to no ganged power-switching. */
-	instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
-	instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG;
-	instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
+	usb_log_debug("OHCI rh: Set power mode to ganged power switching.\n");
+	/* Set port power mode to ganged power-switching. */
+	OHCI_CLR(regs->rh_desc_a, RHDA_NPS_FLAG);
+	OHCI_CLR(regs->rh_desc_a, RHDA_PSM_FLAG);
+
+	/* Turn off power (hub driver will turn this back on)*/
+	OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER);
 
 	/* Set to global over-current */
-	instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
-	instance->registers->rh_desc_a &= ~RHDA_OCPM_FLAG;
+	OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG);
+	OHCI_CLR(regs->rh_desc_a, RHDA_OCPM_FLAG);
 #else
-	/* Set port power mode to no per port power-switching. */
-	instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
-	instance->registers->rh_desc_a |= RHDA_PSM_FLAG;
+	usb_log_debug("OHCI rh: Set power mode to per-port power switching.\n");
+	/* Set port power mode to per port power-switching. */
+	OHCI_CLR(regs->rh_desc_a, RHDA_NPS_FLAG);
+	OHCI_SET(regs->rh_desc_a, RHDA_PSM_FLAG);
 
 	/* Control all ports by global switch and turn them off */
-	instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT);
-	instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
+	OHCI_CLR(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT);
+	OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER);
 
 	/* Return control to per port state */
-	instance->registers->rh_desc_b |=
-		((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT;
+	OHCI_SET(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT);
 
 	/* Set per port over-current */
-	instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
-	instance->registers->rh_desc_a |= RHDA_OCPM_FLAG;
+	OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG);
+	OHCI_SET(regs->rh_desc_a, RHDA_OCPM_FLAG);
 #endif
 
@@ -202,5 +210,5 @@
 	    instance->port_count);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process root hub request.
@@ -226,7 +234,7 @@
 		fibril_mutex_lock(&instance->guard);
 		assert(instance->unfinished_interrupt_transfer == NULL);
-		uint16_t mask = create_interrupt_mask(instance);
+		const uint16_t mask = create_interrupt_mask(instance);
 		if (mask == 0) {
-			usb_log_debug("No changes...\n");
+			usb_log_debug("No changes(%hx)...\n", mask);
 			instance->unfinished_interrupt_transfer = request;
 		} else {
@@ -243,5 +251,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process interrupt on a hub device.
@@ -257,5 +265,5 @@
 	if (instance->unfinished_interrupt_transfer) {
 		usb_log_debug("Finalizing interrupt transfer\n");
-		uint16_t mask = create_interrupt_mask(instance);
+		const uint16_t mask = create_interrupt_mask(instance);
 		interrupt_request(instance->unfinished_interrupt_transfer,
 		    mask, instance->interrupt_mask_size);
@@ -264,5 +272,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Create hub descriptor.
@@ -282,6 +290,6 @@
 	instance->hub_descriptor_size = size;
 
-	uint32_t hub_desc = instance->registers->rh_desc_a;
-	uint32_t port_desc = instance->registers->rh_desc_b;
+	const uint32_t hub_desc = OHCI_RD(instance->registers->rh_desc_a);
+	const uint32_t port_desc = OHCI_RD(instance->registers->rh_desc_b);
 
 	/* bDescLength */
@@ -305,21 +313,19 @@
 	instance->descriptors.hub[4] = 0;
 	/* bPwrOn2PwrGood */
-	instance->descriptors.hub[5] =
-	    (hub_desc >> RHDA_POTPGT_SHIFT) & RHDA_POTPGT_MASK;
+	instance->descriptors.hub[5] = hub_desc >> RHDA_POTPGT_SHIFT;
 	/* bHubContrCurrent, root hubs don't need no power. */
 	instance->descriptors.hub[6] = 0;
 
 	/* Device Removable and some legacy 1.0 stuff*/
-	instance->descriptors.hub[7] =
-	    (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK & 0xff;
+	instance->descriptors.hub[7] = (port_desc >> RHDB_DR_SHIFT) & 0xff;
 	instance->descriptors.hub[8] = 0xff;
 	if (instance->interrupt_mask_size == 2) {
 		instance->descriptors.hub[8] =
-		    (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK >> 8;
+		    (port_desc >> RHDB_DR_SHIFT) >> 8;
 		instance->descriptors.hub[9]  = 0xff;
 		instance->descriptors.hub[10] = 0xff;
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize hub descriptors.
  *
@@ -341,11 +347,11 @@
 	    instance->interrupt_mask_size;
 
-	instance->descriptors.configuration.total_length =
+	instance->descriptors.configuration.total_length = uint16_host2usb(
 	    sizeof(usb_standard_configuration_descriptor_t) +
 	    sizeof(usb_standard_endpoint_descriptor_t) +
 	    sizeof(usb_standard_interface_descriptor_t) +
-	    instance->hub_descriptor_size;
-}
-/*----------------------------------------------------------------------------*/
+	    instance->hub_descriptor_size);
+}
+
 /**
  * Create bitmap of changes to answer status interrupt.
@@ -364,19 +370,19 @@
 
 	/* Only local power source change and over-current change can happen */
-	if (instance->registers->rh_status & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
+	if (OHCI_RD(instance->registers->rh_status)
+	    & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
 		mask |= 1;
 	}
 	for (size_t port = 1; port <= instance->port_count; ++port) {
 		/* Write-clean bits are those that indicate change */
-		if (RHPS_CHANGE_WC_MASK
-		    & instance->registers->rh_port_status[port - 1]) {
-
+		if (OHCI_RD(instance->registers->rh_port_status[port - 1])
+		    & RHPS_CHANGE_WC_MASK) {
 			mask |= (1 << port);
 		}
 	}
-	/* USB is little endian */
-	return host2uint32_t_le(mask);
-}
-/*----------------------------------------------------------------------------*/
+	usb_log_debug2("OHCI root hub interrupt mask: %hx.\n", mask);
+	return uint16_host2usb(mask);
+}
+
 /**
  * Create answer to status request.
@@ -396,4 +402,6 @@
 	usb_device_request_setup_packet_t *request_packet =
 	    (usb_device_request_setup_packet_t*)request->setup_buffer;
+
+	const uint16_t index = uint16_usb2host(request_packet->index);
 
 	switch (request_packet->request_type)
@@ -406,7 +414,8 @@
 			TRANSFER_END(request, EOVERFLOW);
 		} else {
-			uint32_t data = instance->registers->rh_status &
-			    (RHS_LPS_FLAG | RHS_LPSC_FLAG
-			        | RHS_OCI_FLAG | RHS_OCIC_FLAG);
+			const uint32_t data =
+			    OHCI_RD(instance->registers->rh_status) &
+			        (RHS_LPS_FLAG | RHS_LPSC_FLAG
+			            | RHS_OCI_FLAG | RHS_OCIC_FLAG);
 			TRANSFER_END_DATA(request, &data, sizeof(data));
 		}
@@ -420,10 +429,11 @@
 			TRANSFER_END(request, EOVERFLOW);
 		} else {
-			unsigned port = request_packet->index;
+			const unsigned port = index;
 			if (port < 1 || port > instance->port_count)
 				TRANSFER_END(request, EINVAL);
-
-			uint32_t data =
-			    instance->registers->rh_port_status[port - 1];
+			/* Register format matches the format of port status
+			 * field */
+			const uint32_t data = uint32_host2usb(OHCI_RD(
+			    instance->registers->rh_port_status[port - 1]));
 			TRANSFER_END_DATA(request, &data, sizeof(data));
 		}
@@ -434,5 +444,5 @@
 			TRANSFER_END(request, EOVERFLOW);
 		} else {
-			uint16_t data =
+			const uint16_t data =
 			    uint16_host2usb(USB_DEVICE_STATUS_SELF_POWERED);
 			TRANSFER_END_DATA(request, &data, sizeof(data));
@@ -441,10 +451,10 @@
 	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)
+		if (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)
+		if (index >= 2)
 			TRANSFER_END(request, EINVAL);
 
@@ -455,5 +465,5 @@
 		} else {
 			/* Endpoints are OK. (We don't halt) */
-			uint16_t data = 0;
+			const uint16_t data = 0;
 			TRANSFER_END_DATA(request, &data, sizeof(data));
 		}
@@ -465,5 +475,5 @@
 
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Create answer to a descriptor request.
@@ -482,6 +492,8 @@
 	usb_device_request_setup_packet_t *setup_request =
 	    (usb_device_request_setup_packet_t *) request->setup_buffer;
-	uint16_t setup_request_value = setup_request->value_high;
-	switch (setup_request_value)
+	/* "The wValue field specifies the descriptor type in the high byte
+	 * and the descriptor index in the low byte (refer to Table 9-5)." */
+	const int desc_type = uint16_usb2host(setup_request->value) >> 8;
+	switch (desc_type)
 	{
 	case USB_DESCTYPE_HUB:
@@ -530,5 +542,5 @@
 		    setup_request->value,
 		    setup_request->request_type, setup_request->request,
-		    setup_request_value, setup_request->index,
+		    desc_type, setup_request->index,
 		    setup_request->length);
 		TRANSFER_END(request, EINVAL);
@@ -537,5 +549,5 @@
 	TRANSFER_END(request, ENOTSUP);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * process feature-enabling request on hub
@@ -554,21 +566,27 @@
 		return EINVAL;
 
-	switch (feature)
-	{
-	case USB_HUB_FEATURE_PORT_POWER:   //8
-		/* No power switching */
-		if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
-			return EOK;
-		/* Ganged power switching */
-		if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
-			instance->registers->rh_status = RHS_SET_GLOBAL_POWER;
-			return EOK;
+	switch (feature) {
+	case USB_HUB_FEATURE_PORT_POWER:   /*8*/
+		{
+			const uint32_t rhda =
+			    OHCI_RD(instance->registers->rh_desc_a);
+			/* No power switching */
+			if (rhda & RHDA_NPS_FLAG)
+				return EOK;
+			/* Ganged power switching, one port powers all */
+			if (!(rhda & RHDA_PSM_FLAG)) {
+				OHCI_WR(instance->registers->rh_status,
+				    RHS_SET_GLOBAL_POWER);
+				return EOK;
+			}
 		}
-	case USB_HUB_FEATURE_PORT_ENABLE:  //1
-	case USB_HUB_FEATURE_PORT_SUSPEND: //2
-	case USB_HUB_FEATURE_PORT_RESET:   //4
-		/* Nice thing is that these shifts correspond to the position
-		 * of control bits in register */
-		instance->registers->rh_port_status[port - 1] = (1 << feature);
+			/* Fall through */
+	case USB_HUB_FEATURE_PORT_ENABLE:  /*1*/
+	case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/
+	case USB_HUB_FEATURE_PORT_RESET:   /*4*/
+		usb_log_debug2("Setting port POWER, ENABLE, SUSPEND or RESET "
+		    "on port %"PRIu16".\n", port);
+		OHCI_WR(instance->registers->rh_port_status[port - 1],
+		    1 << feature);
 		return EOK;
 	default:
@@ -576,5 +594,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process feature clear request.
@@ -596,35 +614,42 @@
 	switch (feature)
 	{
-	case USB_HUB_FEATURE_PORT_POWER:          //8
-		/* No power switching */
-		if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
-			return ENOTSUP;
-		/* Ganged power switching */
-		if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
-			instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
+	case USB_HUB_FEATURE_PORT_POWER:          /*8*/
+		{
+			const uint32_t rhda =
+			    OHCI_RD(instance->registers->rh_desc_a);
+			/* No power switching */
+			if (rhda & RHDA_NPS_FLAG)
+				return ENOTSUP;
+			/* Ganged power switching, one port powers all */
+			if (!(rhda & RHDA_PSM_FLAG)) {
+				OHCI_WR(instance->registers->rh_status,
+				    RHS_CLEAR_GLOBAL_POWER);
+				return EOK;
+			}
+			OHCI_WR(instance->registers->rh_port_status[port - 1],
+			    RHPS_CLEAR_PORT_POWER);
 			return EOK;
 		}
-		instance->registers->rh_port_status[port - 1] =
-			RHPS_CLEAR_PORT_POWER;
+
+	case USB_HUB_FEATURE_PORT_ENABLE:         /*1*/
+		OHCI_WR(instance->registers->rh_port_status[port - 1],
+		    RHPS_CLEAR_PORT_ENABLE);
 		return EOK;
 
-	case USB_HUB_FEATURE_PORT_ENABLE:         //1
-		instance->registers->rh_port_status[port - 1] =
-			RHPS_CLEAR_PORT_ENABLE;
+	case USB_HUB_FEATURE_PORT_SUSPEND:        /*2*/
+		OHCI_WR(instance->registers->rh_port_status[port - 1],
+		    RHPS_CLEAR_PORT_SUSPEND);
 		return EOK;
 
-	case USB_HUB_FEATURE_PORT_SUSPEND:        //2
-		instance->registers->rh_port_status[port - 1] =
-			RHPS_CLEAR_PORT_SUSPEND;
-		return EOK;
-
-	case USB_HUB_FEATURE_C_PORT_CONNECTION:   //16
-	case USB_HUB_FEATURE_C_PORT_ENABLE:       //17
-	case USB_HUB_FEATURE_C_PORT_SUSPEND:      //18
-	case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: //19
-	case USB_HUB_FEATURE_C_PORT_RESET:        //20
-		/* Nice thing is that these shifts correspond to the position
-		 * of control bits in register */
-		instance->registers->rh_port_status[port - 1] = (1 << feature);
+	case USB_HUB_FEATURE_C_PORT_CONNECTION:   /*16*/
+	case USB_HUB_FEATURE_C_PORT_ENABLE:       /*17*/
+	case USB_HUB_FEATURE_C_PORT_SUSPEND:      /*18*/
+	case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: /*19*/
+	case USB_HUB_FEATURE_C_PORT_RESET:        /*20*/
+		usb_log_debug2("Clearing port C_CONNECTION, C_ENABLE, "
+		    "C_SUSPEND, C_OC or C_RESET on port %"PRIu16".\n", port);
+		/* Bit offsets correspond to the feature number */
+		OHCI_WR(instance->registers->rh_port_status[port - 1],
+		    1 << feature);
 		return EOK;
 
@@ -633,5 +658,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * process one of requests that do not request nor carry additional data
@@ -654,5 +679,5 @@
 	case USB_HUB_REQ_TYPE_SET_PORT_FEATURE:
 		usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
-		int ret = set_feature_port(instance,
+		const int ret = set_feature_port(instance,
 		    setup_request->value, setup_request->index);
 		TRANSFER_END(request, ret);
@@ -671,5 +696,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * process one of requests that do not request nor carry additional data
@@ -693,5 +718,5 @@
 	case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE:
 		usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n");
-		int ret = clear_feature_port(instance,
+		const int ret = clear_feature_port(instance,
 		    setup_request->value, setup_request->index);
 		TRANSFER_END(request, ret);
@@ -706,6 +731,7 @@
 		 * as root hubs do not support local power status feature.
 		 * (OHCI pg. 127) */
-		if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
-			instance->registers->rh_status = RHS_OCIC_FLAG;
+		if (uint16_usb2host(setup_request->value)
+		    == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
+			OHCI_WR(instance->registers->rh_status, RHS_OCIC_FLAG);
 			TRANSFER_END(request, EOK);
 		}
@@ -717,5 +743,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process hub control request.
@@ -771,5 +797,5 @@
 		if (request->buffer_size == 0)
 			TRANSFER_END(request, EOVERFLOW);
-		uint8_t config = 1;
+		const uint8_t config = 1;
 		TRANSFER_END_DATA(request, &config, sizeof(config));
 
@@ -790,10 +816,10 @@
 			TRANSFER_END(request, EINVAL);
 
-		instance->address = setup_request->value;
+		instance->address = uint16_usb2host(setup_request->value);
 		TRANSFER_END(request, EOK);
 
 	case USB_DEVREQ_SET_CONFIGURATION:
 		usb_log_debug("USB_DEVREQ_SET_CONFIGURATION: %u\n",
-		    setup_request->value);
+		    uint16_usb2host(setup_request->value));
 		/* We have only one configuration, it's number is 1 */
 		if (uint16_usb2host(setup_request->value) != 1)
Index: uspace/drv/bus/usb/ohci/utils/malloc32.h
===================================================================
--- uspace/drv/bus/usb/ohci/utils/malloc32.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/ohci/utils/malloc32.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -63,5 +63,5 @@
 	return result;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Physical mallocator simulator
  *
@@ -71,5 +71,5 @@
 static inline void * malloc32(size_t size)
 	{ return memalign(OHCI_ALIGN, size); }
-/*----------------------------------------------------------------------------*/
+
 /** Physical mallocator simulator
  *
Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -50,5 +50,5 @@
 static const irq_pio_range_t uhci_irq_pio_ranges[] = {
 	{
-		.base = 0,	/* filled later */
+		.base = 0,
 		.size = sizeof(uhci_regs_t)
 	}
@@ -56,10 +56,28 @@
 
 static const irq_cmd_t uhci_irq_commands[] = {
-	{ .cmd = CMD_PIO_READ_16, .dstarg = 1, .addr = NULL/*filled later*/},
-	{ .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2,
-	  .value = UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS },
-	{ .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
-	{ .cmd = CMD_PIO_WRITE_A_16, .srcarg = 1, .addr = NULL/*filled later*/},
-	{ .cmd = CMD_ACCEPT },
+	{
+		.cmd = CMD_PIO_READ_16,
+		.dstarg = 1,
+		.addr = NULL
+	},
+	{
+		.cmd = CMD_AND,
+		.srcarg = 1,
+		.dstarg = 2,
+		.value = UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.srcarg = 2,
+		.value = 2
+	},
+	{
+		.cmd = CMD_PIO_WRITE_A_16,
+		.srcarg = 1,
+		.addr = NULL
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
 };
 
@@ -72,5 +90,5 @@
 static int hc_debug_checker(void *arg);
 
-/*----------------------------------------------------------------------------*/
+
 /** Get number of PIO ranges used in IRQ code.
  * @return Number of ranges.
@@ -80,5 +98,5 @@
 	return sizeof(uhci_irq_pio_ranges) / sizeof(irq_pio_range_t);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Get number of commands used in IRQ code.
  * @return Number of commands.
@@ -88,5 +106,5 @@
 	return sizeof(uhci_irq_commands) / sizeof(irq_cmd_t);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Generate IRQ code.
  * @param[out] ranges PIO ranges buffer.
@@ -118,5 +136,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Take action based on the interrupt cause.
  *
@@ -175,5 +193,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize UHCI hc driver structure
  *
@@ -235,5 +253,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize UHCI hc hw resources.
  *
@@ -277,5 +295,5 @@
 	    UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize UHCI hc memory structures.
  *
@@ -319,5 +337,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize UHCI hc transfer lists.
  *
@@ -381,5 +399,5 @@
 #undef CHECK_RET_CLEAR_RETURN
 }
-/*----------------------------------------------------------------------------*/
+
 /** Schedule batch for execution.
  *
@@ -409,5 +427,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Polling function, emulates interrupts.
  *
@@ -432,5 +450,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Debug function, checks consistency of memory structures.
  *
Index: uspace/drv/bus/usb/uhci/hw_struct/queue_head.h
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/queue_head.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/uhci/hw_struct/queue_head.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -47,5 +47,5 @@
 	volatile link_pointer_t element;
 } __attribute__((packed)) qh_t;
-/*----------------------------------------------------------------------------*/
+
 /** Initialize queue head structure
  *
@@ -61,5 +61,5 @@
 	instance->next = LINK_POINTER_TERM;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Set queue head next pointer
  *
@@ -81,5 +81,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Set queue head element pointer
  *
Index: uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -107,5 +107,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Convert TD status into standard error code
  *
@@ -145,5 +145,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Print values in status field (dw1) in a human readable way.
  *
Index: uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -100,5 +100,5 @@
 
 void td_print_status(const td_t *instance);
-/*----------------------------------------------------------------------------*/
+
 /** Helper function for parsing actual size out of TD.
  *
@@ -113,5 +113,5 @@
 	return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Check whether less than max data were received on SPD marked transfer.
  *
@@ -129,5 +129,5 @@
 	    (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Helper function for parsing value of toggle bit.
  *
@@ -140,5 +140,5 @@
 	return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Helper function for parsing value of active bit
  *
@@ -151,5 +151,5 @@
 	return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Helper function for setting IOC bit.
  *
@@ -161,5 +161,5 @@
 	instance->status |= TD_STATUS_IOC_FLAG;
 }
-/*----------------------------------------------------------------------------*/
+
 #endif
 /**
Index: uspace/drv/bus/usb/uhci/main.c
===================================================================
--- uspace/drv/bus/usb/uhci/main.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/uhci/main.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -44,14 +44,14 @@
 
 static int uhci_dev_add(ddf_dev_t *device);
-/*----------------------------------------------------------------------------*/
+
 static driver_ops_t uhci_driver_ops = {
 	.dev_add = uhci_dev_add,
 };
-/*----------------------------------------------------------------------------*/
+
 static driver_t uhci_driver = {
 	.name = NAME,
 	.driver_ops = &uhci_driver_ops
 };
-/*----------------------------------------------------------------------------*/
+
 /** Initialize a new ddf driver instance for uhci hc and hub.
  *
@@ -75,5 +75,5 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize global driver structures (NONE).
  *
Index: uspace/drv/bus/usb/uhci/transfer_list.c
===================================================================
--- uspace/drv/bus/usb/uhci/transfer_list.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/uhci/transfer_list.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -42,5 +42,5 @@
 static void transfer_list_remove_batch(
     transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch);
-/*----------------------------------------------------------------------------*/
+
 /** Initialize transfer list structures.
  *
@@ -69,5 +69,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Dispose transfer list structures.
  *
@@ -97,5 +97,5 @@
 	qh_set_next_qh(instance->queue_head, next->queue_head);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Add transfer batch to the list and queue.
  *
@@ -144,5 +144,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Add completed batches to the provided list.
  *
@@ -171,5 +171,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Walk the list and finish all batches with EINTR.
  *
@@ -188,5 +188,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Remove a transfer batch from the list and queue.
  *
Index: uspace/drv/bus/usb/uhci/uhci.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/uhci/uhci.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -65,5 +65,5 @@
 	return dev->driver_data;
 }
-/*----------------------------------------------------------------------------*/
+
 /** IRQ handling callback, forward status from call to diver structure.
  *
@@ -83,10 +83,10 @@
 	hc_interrupt(&uhci->hc, status);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Operations supported by the HC driver */
 static ddf_dev_ops_t hc_ops = {
 	.interfaces[USBHC_DEV_IFACE] = &hcd_iface, /* see iface.h/c */
 };
-/*----------------------------------------------------------------------------*/
+
 /** Gets handle of the respective hc.
  *
@@ -105,10 +105,10 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** USB interface implementation used by RH */
 static usb_iface_t usb_iface = {
 	.get_hc_handle = usb_iface_get_hc_handle,
 };
-/*----------------------------------------------------------------------------*/
+
 /** Get root hub hw resources (I/O registers).
  *
@@ -123,5 +123,5 @@
 	return &rh->resource_list;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Interface to provide the root hub driver with hw info */
 static hw_res_ops_t hw_res_iface = {
@@ -129,5 +129,5 @@
 	.enable_interrupt = NULL,
 };
-/*----------------------------------------------------------------------------*/
+
 /** RH function support for uhci_rhd */
 static ddf_dev_ops_t rh_ops = {
@@ -135,5 +135,5 @@
 	.interfaces[HW_RES_DEV_IFACE] = &hw_res_iface
 };
-/*----------------------------------------------------------------------------*/
+
 /** Initialize hc and rh DDF structures and their respective drivers.
  *
Index: uspace/drv/bus/usb/uhci/uhci_batch.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci_batch.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/uhci/uhci_batch.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -58,5 +58,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Finishes usb_transfer_batch and destroys the structure.
  *
@@ -71,8 +71,8 @@
 	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.
  *
@@ -143,5 +143,5 @@
 	return uhci_batch;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Check batch TDs for activity.
  *
@@ -196,5 +196,5 @@
 	return true;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Direction to pid conversion table */
 static const usb_packet_id direction_pids[] = {
@@ -202,5 +202,5 @@
 	[USB_DIRECTION_OUT] = USB_PID_OUT,
 };
-/*----------------------------------------------------------------------------*/
+
 /** Prepare generic data transfer
  *
@@ -259,5 +259,5 @@
 	    USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch));
 }
-/*----------------------------------------------------------------------------*/
+
 /** Prepare generic control transfer
  *
@@ -331,5 +331,5 @@
 	    uhci_batch->tds[td].status);
 }
-/*----------------------------------------------------------------------------*/
+
 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t) =
 {
Index: uspace/drv/bus/usb/uhci/uhci_batch.h
===================================================================
--- uspace/drv/bus/usb/uhci/uhci_batch.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/uhci/uhci_batch.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -76,5 +76,5 @@
 	    uhci_batch->td_count * sizeof(td_t);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Get offset to data buffer accessible to the HC hw.
  * @param uhci_batch UHCI batch structure.
@@ -89,5 +89,5 @@
 	    uhci_batch->usb_batch->setup_size;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Aborts the batch.
  * Sets error to EINTR and size off transferd data to 0, before finishing the
@@ -103,5 +103,5 @@
 	uhci_transfer_batch_finish_dispose(uhci_batch);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Linked list conversion wrapper.
  * @param l Linked list link.
Index: uspace/drv/bus/usb/uhci/utils/malloc32.h
===================================================================
--- uspace/drv/bus/usb/uhci/utils/malloc32.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/uhci/utils/malloc32.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -35,10 +35,11 @@
 #define DRV_UHCI_UTILS_MALLOC32_H
 
+#include <as.h>
 #include <assert.h>
-#include <unistd.h>
+#include <ddi.h>
 #include <errno.h>
 #include <malloc.h>
 #include <mem.h>
-#include <as.h>
+#include <unistd.h>
 
 #define UHCI_STRCUTURES_ALIGNMENT 16
@@ -63,5 +64,5 @@
 	return result;
 }
-/*----------------------------------------------------------------------------*/
+
 /** DMA malloc simulator
  *
@@ -85,5 +86,5 @@
 	return memalign(alignment, size);
 }
-/*----------------------------------------------------------------------------*/
+
 /** DMA malloc simulator
  *
@@ -92,5 +93,5 @@
 static inline void free32(void *addr)
 	{ free(addr); }
-/*----------------------------------------------------------------------------*/
+
 /** Create 4KB page mapping
  *
@@ -99,16 +100,13 @@
 static inline void * get_page(void)
 {
-	void *address = as_area_create(AS_AREA_ANY, UHCI_REQUIRED_PAGE_SIZE,
-	    AS_AREA_READ | AS_AREA_WRITE);
-	if (address == AS_MAP_FAILED)
-		return NULL;
-	
-	return address;
+	void *address, *phys;
+	const int ret = dmamem_map_anonymous(UHCI_REQUIRED_PAGE_SIZE,
+	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, &address);
+	return ret == EOK ? address : NULL;
 }
-/*----------------------------------------------------------------------------*/
+
 static inline void return_page(void *page)
 {
-	if (page)
-		as_area_destroy(page);
+	dmamem_unmap_anonymous(page);
 }
 
Index: uspace/drv/bus/usb/uhcirh/port.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/port.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/uhcirh/port.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -63,5 +63,5 @@
 	return pio_read_16(port->address);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Register writing helper function.
  *
@@ -75,5 +75,5 @@
 	pio_write_16(port->address, val);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize UHCI root hub port instance.
  *
@@ -127,5 +127,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Cleanup UHCI root hub port instance.
  *
@@ -141,5 +141,5 @@
 	return;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Periodically checks port status and reports new devices.
  *
@@ -210,5 +210,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback for enabling port during adding a new device.
  *
@@ -247,5 +247,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize and report connected device.
  *
@@ -282,5 +282,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Remove device.
  *
@@ -324,5 +324,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Enable or disable root hub port.
  *
@@ -358,5 +358,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Print the port status value in a human friendly way
  *
Index: uspace/drv/bus/usb/uhcirh/root_hub.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/root_hub.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/uhcirh/root_hub.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -79,5 +79,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Cleanup UHCI root hub instance.
  *
@@ -92,5 +92,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * @}
Index: uspace/drv/bus/usb/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -46,5 +46,5 @@
 #include "usbhid.h"
 
-/*----------------------------------------------------------------------------*/
+
 
 const usb_endpoint_description_t usb_hid_generic_poll_endpoint_description = {
@@ -60,5 +60,5 @@
 const char *HID_GENERIC_CLASS_NAME = "hid";
 
-/*----------------------------------------------------------------------------*/
+
 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun);
 static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer,
@@ -68,5 +68,5 @@
 static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc,
     size_t size, size_t *actual_size);
-/*----------------------------------------------------------------------------*/
+
 static usbhid_iface_t usb_generic_iface = {
 	.get_event = usb_generic_hid_get_event,
@@ -75,10 +75,10 @@
 	.get_report_descriptor = usb_generic_get_report_descriptor
 };
-/*----------------------------------------------------------------------------*/
+
 static ddf_dev_ops_t usb_generic_hid_ops = {
 	.interfaces[USBHID_DEV_IFACE] = &usb_generic_iface,
 	.open = usb_generic_hid_client_connected
 };
-/*----------------------------------------------------------------------------*/
+
 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun)
 {
@@ -97,5 +97,5 @@
 	return hid_dev->max_input_report_size;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer,
     size_t size, size_t *act_size, int *event_nr, unsigned int flags)
@@ -127,5 +127,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun)
 {
@@ -144,5 +144,5 @@
 	return hid_dev->report_desc_size;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc,
     size_t size, size_t *actual_size)
@@ -166,5 +166,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_generic_hid_client_connected(ddf_fun_t *fun)
 {
@@ -172,5 +172,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 void usb_generic_hid_deinit(usb_hid_dev_t *hid_dev, void *data)
 {
@@ -189,5 +189,5 @@
 	ddf_fun_destroy(fun);
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_generic_hid_init(usb_hid_dev_t *hid_dev, void **data)
 {
@@ -224,5 +224,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, void *data)
 {
Index: uspace/drv/bus/usb/usbhid/generic/hiddev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/generic/hiddev.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/generic/hiddev.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -47,5 +47,5 @@
 const char *HID_GENERIC_CLASS_NAME;
 
-/*----------------------------------------------------------------------------*/
+
 
 int usb_generic_hid_init(struct usb_hid_dev *hid_dev, void **data);
Index: uspace/drv/bus/usb/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -71,5 +71,7 @@
 #include "../usbhid.h"
 
-/*----------------------------------------------------------------------------*/
+static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
+static ddf_dev_ops_t kbdops = { .default_handler = default_connection_handler };
+
 
 static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK;
@@ -86,5 +88,5 @@
 static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000;
 
-/*----------------------------------------------------------------------------*/
+
 /** Keyboard polling endpoint description for boot protocol class. */
 const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
@@ -101,5 +103,5 @@
 
 static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
-/*----------------------------------------------------------------------------*/
+
 static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[] = {
 	0x05, 0x01,  /* Usage Page (Generic Desktop), */
@@ -136,5 +138,5 @@
 	0xC0         /* End Collection */
 };
-/*----------------------------------------------------------------------------*/
+
 typedef enum usb_kbd_flags {
 	USB_KBD_STATUS_UNINITIALIZED = 0,
@@ -142,7 +144,7 @@
 	USB_KBD_STATUS_TO_DESTROY = -1
 } usb_kbd_flags;
-/*----------------------------------------------------------------------------*/
+
 /* IPC method handler                                                         */
-/*----------------------------------------------------------------------------*/
+
 /**
  * Default handler for IPC methods not handled by DDF.
@@ -187,6 +189,6 @@
 			break;
 		}
-		if (kbd_dev->console_sess == NULL) {
-			kbd_dev->console_sess = sess;
+		if (kbd_dev->client_sess == NULL) {
+			kbd_dev->client_sess = sess;
 			usb_log_debug("%s: OK\n", __FUNCTION__);
 			async_answer_0(icallid, EOK);
@@ -206,7 +208,7 @@
 
 }
-/*----------------------------------------------------------------------------*/
+
 /* Key processing functions                                                   */
-/*----------------------------------------------------------------------------*/
+
 /**
  * Handles turning of LED lights on and off.
@@ -281,5 +283,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Send key event.
  *
@@ -292,5 +294,5 @@
 {
 	usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key);
-	if (kbd_dev->console_sess == NULL) {
+	if (kbd_dev->client_sess == NULL) {
 		usb_log_warning(
 		    "Connection to console not ready, key discarded.\n");
@@ -298,5 +300,5 @@
 	}
 
-	async_exch_t *exch = async_exchange_begin(kbd_dev->console_sess);
+	async_exch_t *exch = async_exchange_begin(kbd_dev->client_sess);
 	if (exch != NULL) {
 		async_msg_2(exch, KBDEV_EVENT, type, key);
@@ -306,5 +308,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 static inline int usb_kbd_is_lock(unsigned int key_code)
 {
@@ -313,5 +315,5 @@
 	    || key_code == KC_CAPS_LOCK);
 }
-/*----------------------------------------------------------------------------*/
+
 static size_t find_in_array_int32(int32_t val, int32_t *arr, size_t arr_size)
 {
@@ -324,5 +326,5 @@
 	return (size_t) -1;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Checks if some keys were pressed or released and generates key events.
@@ -407,7 +409,7 @@
 	usb_log_debug2("Stored keys %s.\n", key_buffer);
 }
-/*----------------------------------------------------------------------------*/
+
 /* General kbd functions                                                      */
-/*----------------------------------------------------------------------------*/
+
 /**
  * Processes data received from the device in form of report.
@@ -479,7 +481,7 @@
 	usb_kbd_check_key_changes(hid_dev, kbd_dev);
 }
-/*----------------------------------------------------------------------------*/
+
 /* HID/KBD structure manipulation                                             */
-/*----------------------------------------------------------------------------*/
+
 static int usb_kbd_create_function(usb_kbd_t *kbd_dev)
 {
@@ -499,5 +501,5 @@
 	/* Store the initialized HID device and HID ops
 	 * to the DDF function. */
-	fun->ops = &kbd_dev->ops;
+	fun->ops = &kbdops;
 	fun->driver_data = kbd_dev;
 
@@ -535,7 +537,7 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /* API functions                                                              */
-/*----------------------------------------------------------------------------*/
+
 /**
  * Initialization of the USB/HID keyboard structure.
@@ -576,5 +578,4 @@
 	fibril_mutex_initialize(&kbd_dev->repeat_mtx);
 	kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
-	kbd_dev->ops.default_handler = default_connection_handler;
 
 	/* Store link to HID device */
@@ -700,5 +701,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data)
 {
@@ -714,15 +715,15 @@
 	return true;
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
 {
 	return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
 {
 	return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Properly destroys the USB/HID keyboard structure.
@@ -737,6 +738,6 @@
 
 	/* Hangup session to the console. */
-	if (kbd_dev->console_sess)
-		async_hangup(kbd_dev->console_sess);
+	if (kbd_dev->client_sess)
+		async_hangup(kbd_dev->client_sess);
 
 	//assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
@@ -765,5 +766,5 @@
 	free(kbd_dev);
 }
-/*----------------------------------------------------------------------------*/
+
 void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
 {
@@ -778,5 +779,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
 {
Index: uspace/drv/bus/usb/usbhid/kbd/kbddev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbddev.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/kbd/kbddev.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -50,5 +50,5 @@
 struct usb_hid_dev;
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * USB/HID keyboard device type.
@@ -82,9 +82,6 @@
 	unsigned lock_keys;
 
-	/** IPC session to the console device (for sending key events). */
-	async_sess_t *console_sess;
-
-	/** @todo What is this actually? */
-	ddf_dev_ops_t ops;
+	/** IPC session to client (for sending key events). */
+	async_sess_t *client_sess;
 
 	/** Information for auto-repeat of keys. */
@@ -116,5 +113,5 @@
 } usb_kbd_t;
 
-/*----------------------------------------------------------------------------*/
+
 
 extern const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description;
@@ -123,5 +120,5 @@
 const char *HID_KBD_CLASS_NAME;
 
-/*----------------------------------------------------------------------------*/
+
 
 int usb_kbd_init(struct usb_hid_dev *hid_dev, void **data);
Index: uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -105,5 +105,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Main routine to be executed by a fibril for handling auto-repeat.
@@ -132,5 +132,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Start repeating particular key.
@@ -149,5 +149,5 @@
 	fibril_mutex_unlock(&kbd->repeat_mtx);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Stop repeating particular key.
Index: uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.h
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -42,5 +42,5 @@
 struct usb_kbd_t;
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Structure for keeping information needed for auto-repeat of keys.
@@ -57,5 +57,5 @@
 } usb_kbd_repeat_t;
 
-/*----------------------------------------------------------------------------*/
+
 
 int usb_kbd_repeat_fibril(void *arg);
Index: uspace/drv/bus/usb/usbhid/main.c
===================================================================
--- uspace/drv/bus/usb/usbhid/main.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/main.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -113,5 +113,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Callback for a device about to be removed from the driver.
@@ -126,5 +126,5 @@
 	return ENOTSUP;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Callback for removing a device from the driver.
@@ -152,5 +152,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** USB generic driver callbacks */
 static const usb_driver_ops_t usb_hid_driver_ops = {
@@ -159,5 +159,5 @@
 	.device_gone = usb_hid_device_gone,
 };
-/*----------------------------------------------------------------------------*/
+
 /** The driver itself. */
 static const usb_driver_t usb_hid_driver = {
@@ -166,5 +166,5 @@
         .endpoints = usb_hid_endpoints
 };
-/*----------------------------------------------------------------------------*/
+
 int main(int argc, char *argv[])
 {
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -54,5 +54,8 @@
 #define NAME "mouse"
 
-/*----------------------------------------------------------------------------*/
+static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
+
+static ddf_dev_ops_t ops = { .default_handler = default_connection_handler };
+
 
 const usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
@@ -71,5 +74,5 @@
 static const uint8_t IDLE_RATE = 0;
 
-/*----------------------------------------------------------------------------*/
+
 static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[] = {
 	0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
@@ -101,5 +104,5 @@
 };
 
-/*----------------------------------------------------------------------------*/
+
 
 /** Default handler for IPC methods not handled by DDF.
@@ -143,5 +146,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 static int get_mouse_axis_move_value(uint8_t rid, usb_hid_report_t *report,
     int32_t usage)
@@ -221,20 +224,10 @@
 		assert(index < mouse_dev->buttons_count);
 
-		if (mouse_dev->buttons[index] == 0 && field->value != 0) {
+		if (mouse_dev->buttons[index] != field->value) {
 			async_exch_t *exch =
 			    async_exchange_begin(mouse_dev->mouse_sess);
 			if (exch != NULL) {
 				async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
-				    field->usage, 1);
-				async_exchange_end(exch);
-				mouse_dev->buttons[index] = field->value;
-			}
-
-		} else if (mouse_dev->buttons[index] != 0 && field->value == 0) {
-			async_exch_t *exch =
-			    async_exchange_begin(mouse_dev->mouse_sess);
-			if (exch != NULL) {
-				async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
-				    field->usage, 0);
+				    field->usage, (field->value != 0) ? 1 : 0);
 				async_exchange_end(exch);
 				mouse_dev->buttons[index] = field->value;
@@ -252,5 +245,5 @@
 	return true;
 }
-/*----------------------------------------------------------------------------*/
+
 #define FUN_UNBIND_DESTROY(fun) \
 if (fun) { \
@@ -263,5 +256,5 @@
 	} \
 } else (void)0
-/*----------------------------------------------------------------------------*/
+
 static int usb_mouse_create_function(usb_hid_dev_t *hid_dev, usb_mouse_t *mouse)
 {
@@ -279,5 +272,5 @@
 	}
 
-	fun->ops = &mouse->ops;
+	fun->ops = &ops;
 	fun->driver_data = mouse;
 
@@ -302,5 +295,4 @@
 	}
 	mouse->mouse_fun = fun;
-
 	return EOK;
 }
@@ -345,5 +337,5 @@
 	return highest_button;
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
 {
@@ -379,7 +371,4 @@
 	}
 
-	// set handler for incoming calls
-	mouse_dev->ops.default_handler = default_connection_handler;
-
 	// TODO: how to know if the device supports the request???
 	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
@@ -398,5 +387,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, void *data)
 {
@@ -411,5 +400,5 @@
 	return usb_mouse_process_report(hid_dev, mouse_dev);
 }
-/*----------------------------------------------------------------------------*/
+
 void usb_mouse_deinit(usb_hid_dev_t *hid_dev, void *data)
 {
@@ -432,5 +421,5 @@
 	free(mouse_dev);
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
 {
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -42,9 +42,9 @@
 struct usb_hid_dev;
 
-/*----------------------------------------------------------------------------*/
+
 
 /** Container for USB mouse device. */
 typedef struct {
-	/** IPC session to console (consumer). */
+	/** IPC session to consumer. */
 	async_sess_t *mouse_sess;
 
@@ -53,10 +53,9 @@
 	size_t buttons_count;
 
-	ddf_dev_ops_t ops;
 	/* DDF mouse function */
 	ddf_fun_t *mouse_fun;
 } usb_mouse_t;
 
-/*----------------------------------------------------------------------------*/
+
 
 extern const usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description;
@@ -65,5 +64,5 @@
 const char *HID_MOUSE_CATEGORY;
 
-/*----------------------------------------------------------------------------*/
+
 
 int usb_mouse_init(struct usb_hid_dev *hid_dev, void **data);
@@ -75,5 +74,5 @@
 int usb_mouse_set_boot_protocol(struct usb_hid_dev *hid_dev);
 
-/*----------------------------------------------------------------------------*/
+
 
 #endif // USB_HID_MOUSEDEV_H_
Index: uspace/drv/bus/usb/usbhid/multimedia/multimedia.c
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -54,5 +54,5 @@
 #define NAME  "multimedia-keys"
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Logitech UltraX device type.
@@ -70,5 +70,5 @@
 
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Default handler for IPC methods not handled by DDF.
@@ -106,9 +106,9 @@
 		async_answer_0(icallid, EINVAL);
 }
-/*----------------------------------------------------------------------------*/
+
 static ddf_dev_ops_t multimedia_ops = {
 	.default_handler = default_connection_handler
 };
-/*----------------------------------------------------------------------------*/
+
 /**
  * Processes key events.
@@ -155,5 +155,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
 {
@@ -216,5 +216,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data)
 {
@@ -239,5 +239,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data)
 {
Index: uspace/drv/bus/usb/usbhid/multimedia/multimedia.h
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/multimedia.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/multimedia/multimedia.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -41,5 +41,5 @@
 struct usb_hid_dev;
 
-/*----------------------------------------------------------------------------*/
+
 
 int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data);
@@ -49,5 +49,5 @@
 bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data);
 
-/*----------------------------------------------------------------------------*/
+
 
 #endif // USB_HID_MULTIMEDIA_H_
Index: uspace/drv/bus/usb/usbhid/subdrivers.h
===================================================================
--- uspace/drv/bus/usb/usbhid/subdrivers.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/subdrivers.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -40,5 +40,5 @@
 #include "kbd/kbddev.h"
 
-/*----------------------------------------------------------------------------*/
+
 
 typedef struct usb_hid_subdriver_usage {
@@ -47,5 +47,5 @@
 } usb_hid_subdriver_usage_t;
 
-/*----------------------------------------------------------------------------*/
+
 
 /** Structure representing the mapping between device requirements and the 
@@ -81,10 +81,10 @@
 } usb_hid_subdriver_mapping_t;
 
-/*----------------------------------------------------------------------------*/
+
 
 extern const usb_hid_subdriver_mapping_t usb_hid_subdrivers[];
 extern const size_t USB_HID_MAX_SUBDRIVERS;
 
-/*----------------------------------------------------------------------------*/
+
 
 #endif /* USB_HID_SUBDRIVERS_H_ */
Index: uspace/drv/bus/usb/usbhid/usbhid.c
===================================================================
--- uspace/drv/bus/usb/usbhid/usbhid.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/usbhid.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -58,5 +58,5 @@
 	NULL
 };
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
 {
@@ -74,5 +74,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
 {
@@ -90,5 +90,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
 {
@@ -110,5 +110,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static bool usb_hid_ids_match(const usb_hid_dev_t *hid_dev,
     const usb_hid_subdriver_mapping_t *mapping)
@@ -122,5 +122,5 @@
 	    == mapping->product_id);
 }
-/*----------------------------------------------------------------------------*/
+
 static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
     const usb_hid_subdriver_mapping_t *mapping)
@@ -178,5 +178,5 @@
 	return matches;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
     const usb_hid_subdriver_t **subdrivers, unsigned count)
@@ -211,5 +211,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
 {
@@ -263,5 +263,5 @@
 	return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, const usb_device_t *dev)
 {
@@ -290,5 +290,5 @@
 	return ENOTSUP;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
 {
@@ -322,5 +322,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /*
  * This functions initializes required structures from the device's descriptors
@@ -458,5 +458,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
     size_t buffer_size, void *arg)
@@ -500,5 +500,5 @@
 	return cont;
 }
-/*----------------------------------------------------------------------------*/
+
 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg)
 {
@@ -517,15 +517,15 @@
 	hid_dev->running = false;
 }
-/*----------------------------------------------------------------------------*/
+
 void usb_hid_new_report(usb_hid_dev_t *hid_dev)
 {
 	++hid_dev->report_nr;
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_hid_report_number(const usb_hid_dev_t *hid_dev)
 {
 	return hid_dev->report_nr;
 }
-/*----------------------------------------------------------------------------*/
+
 void usb_hid_deinit(usb_hid_dev_t *hid_dev)
 {
Index: uspace/drv/bus/usb/usbhid/usbhid.h
===================================================================
--- uspace/drv/bus/usb/usbhid/usbhid.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhid/usbhid.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -95,5 +95,5 @@
 };
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Structure for holding general HID device data.
@@ -132,5 +132,5 @@
 };
 
-/*----------------------------------------------------------------------------*/
+
 
 enum {
@@ -143,5 +143,5 @@
 extern const usb_endpoint_description_t *usb_hid_endpoints[];
 
-/*----------------------------------------------------------------------------*/
+
 
 int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev);
Index: uspace/drv/bus/usb/usbhub/port.c
===================================================================
--- uspace/drv/bus/usb/usbhub/port.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhub/port.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -70,5 +70,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Clear feature on hub port.
@@ -92,5 +92,5 @@
 	    sizeof(clear_request), NULL, 0);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Set feature on hub port.
@@ -114,5 +114,5 @@
 	    sizeof(clear_request), NULL, 0);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Mark reset process as failed due to external reasons
@@ -129,5 +129,5 @@
 	fibril_mutex_unlock(&port->mutex);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process interrupts on given port
@@ -245,5 +245,5 @@
 	    port->port_number, status);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * routine called when a device on port has been removed
@@ -299,5 +299,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process port reset change
@@ -335,5 +335,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Retrieve port status.
  *
@@ -352,5 +352,5 @@
 		.request = USB_HUB_REQUEST_GET_STATUS,
 		.value = 0,
-		.index = port->port_number,
+		.index = uint16_host2usb(port->port_number),
 		.length = sizeof(usb_port_status_t),
 	};
@@ -375,5 +375,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback for enabling a specific port.
  *
@@ -407,5 +407,5 @@
 	return port->reset_okay ? EOK : ESTALL;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Fibril for adding a new device.
  *
@@ -454,5 +454,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Start device adding when connection change is detected.
  *
Index: uspace/drv/bus/usb/usbhub/status.h
===================================================================
--- uspace/drv/bus/usb/usbhub/status.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhub/status.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -42,6 +42,7 @@
  * should not be accessed directly, use supplied getter/setter methods.
  *
- * For more information refer to table 11-15 in
- * "Universal Serial Bus Specification Revision 1.1"
+ * For more information refer to tables 11-15 and 11-16 in
+ * "Universal Serial Bus Specification Revision 1.1" pages 274 and 277
+ * (290 and 293 in pdf)
  *
  */
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -165,5 +165,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Turn off power to all ports.
@@ -176,5 +176,5 @@
 	return ENOTSUP;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Remove all attached devices
@@ -219,5 +219,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback for polling hub for changes.
  *
@@ -256,5 +256,5 @@
 	return true;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Load hub-specific information into hub_dev structure and process if needed
@@ -331,5 +331,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Set configuration of and USB device
@@ -378,5 +378,5 @@
 	return opResult;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process hub over current change
@@ -416,5 +416,5 @@
 
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process hub interrupts.
@@ -485,5 +485,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * callback called from hub polling fibril when the fibril terminates
Index: uspace/drv/bus/usb/usbmid/main.c
===================================================================
--- uspace/drv/bus/usb/usbmid/main.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/bus/usb/usbmid/main.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -61,5 +61,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback when a MID device is about to be removed from the host.
  *
@@ -115,5 +115,5 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback when a MID device was removed from the host.
  *
Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/char/i8042/i8042.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -120,5 +120,5 @@
 	},
 	{
-		.cmd = CMD_BTEST,
+		.cmd = CMD_AND,
 		.value = i8042_OUTPUT_FULL,
 		.srcarg = 1,
Index: uspace/drv/infrastructure/rootmac/rootmac.c
===================================================================
--- uspace/drv/infrastructure/rootmac/rootmac.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/infrastructure/rootmac/rootmac.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -52,10 +52,20 @@
 } rootmac_fun_t;
 
-static hw_resource_t pci_conf_regs = {
-	.type = IO_RANGE,
-	.res.io_range = {
-		.address = 0xCF8,
-		.size = 8,
-		.endianness = LITTLE_ENDIAN
+static hw_resource_t pci_conf_regs[] = {
+	{
+		.type = IO_RANGE,
+		.res.io_range = {
+			.address = 0xfec00000,
+			.size = 4,
+			.endianness = LITTLE_ENDIAN
+		}
+	},
+	{
+		.type = IO_RANGE,
+		.res.io_range = {
+			.address = 0xfee00000,
+			.size = 4,
+			.endianness = LITTLE_ENDIAN
+		}
 	}
 };
@@ -63,6 +73,6 @@
 static rootmac_fun_t pci_data = {
 	.hw_resources = {
-		1,
-		&pci_conf_regs
+		2,
+		pci_conf_regs
 	}
 };
@@ -127,7 +137,12 @@
 static int rootmac_dev_add(ddf_dev_t *dev)
 {
+#if 0
 	/* Register functions */
-	if (!rootmac_add_fun(dev, "pci0", "pangea_pci", &pci_data))
+	if (!rootmac_add_fun(dev, "pci0", "intel_pci", &pci_data))
 		ddf_msg(LVL_ERROR, "Failed to add functions for Mac platform.");
+#else
+	(void)pci_data;
+	(void)rootmac_add_fun;
+#endif
 	
 	return EOK;
Index: uspace/drv/infrastructure/rootpc/rootpc.c
===================================================================
--- uspace/drv/infrastructure/rootpc/rootpc.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/infrastructure/rootpc/rootpc.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -75,10 +75,20 @@
 };
 
-static hw_resource_t pci_conf_regs = {
-	.type = IO_RANGE,
-	.res.io_range = {
-		.address = 0xCF8,
-		.size = 8,
-		.endianness = LITTLE_ENDIAN
+static hw_resource_t pci_conf_regs[] = {
+	{
+		.type = IO_RANGE,
+		.res.io_range = {
+			.address = 0xCF8,
+			.size = 4,
+			.endianness = LITTLE_ENDIAN
+		}
+	},
+	{
+		.type = IO_RANGE,
+		.res.io_range = {
+			.address = 0xCFC,
+			.size = 4,
+			.endianness = LITTLE_ENDIAN
+		}
 	}
 };
@@ -86,6 +96,6 @@
 static rootpc_fun_t pci_data = {
 	.hw_resources = {
-		1,
-		&pci_conf_regs
+		sizeof(pci_conf_regs)/sizeof(pci_conf_regs[0]),
+		pci_conf_regs
 	}
 };
Index: uspace/drv/nic/ne2k/dp8390.c
===================================================================
--- uspace/drv/nic/ne2k/dp8390.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/nic/ne2k/dp8390.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -201,5 +201,5 @@
 	/* Check if the DP8390 is really there */
 	uint8_t val = pio_read_8(ne2k->port + DP_CR);
-	if ((val & (CR_STP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT))
+	if ((val & (CR_STP | CR_TXP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT))
 		return EXDEV;
 	
Index: uspace/drv/nic/ne2k/ne2k.c
===================================================================
--- uspace/drv/nic/ne2k/ne2k.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -83,5 +83,5 @@
 	{
 		/* Mask supported interrupt causes */
-		.cmd = CMD_BTEST,
+		.cmd = CMD_AND,
 		.value = (ISR_PRX | ISR_PTX | ISR_RXE | ISR_TXE | ISR_OVW |
 		    ISR_CNT | ISR_RDC),
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/Makefile	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -71,4 +71,5 @@
 	generic/device/nic.c \
 	generic/device/pci.c \
+	generic/device/ahci.c \
 	generic/elf/elf_load.c \
 	generic/event.c \
Index: uspace/lib/c/arch/abs32le/_link.ld.in
===================================================================
--- uspace/lib/c/arch/abs32le/_link.ld.in	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/abs32le/_link.ld.in	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -14,12 +14,16 @@
 SECTIONS {
 #ifdef LOADER
+	. = 0x70001000 + SIZEOF_HEADERS;
+	
 	.interp : {
 		*(.interp);
-	} :interp
-	
-	. = 0x70001000 + SIZEOF_HEADERS;
+	} :interp :text
 #else
 	. = 0x1000 + SIZEOF_HEADERS;
 #endif
+	
+	/* Make sure the code is aligned reasonably */
+	. = ALIGN(., 16);
+	
 	.text : {
 		*(.text .text.*);
Index: uspace/lib/c/arch/amd64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/amd64/_link.ld.in	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/amd64/_link.ld.in	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -15,12 +15,16 @@
 SECTIONS {
 #ifdef LOADER
+	. = 0x70001000 + SIZEOF_HEADERS;
+	
 	.interp : {
 		*(.interp);
-	} :interp
-	
-	. = 0x70001000 + SIZEOF_HEADERS;
+	} :interp :text
 #else
 	. = 0x1000 + SIZEOF_HEADERS;
 #endif
+	
+	/* Make sure the code is aligned reasonably */
+	. = ALIGN(., 16);
+	
 	.init : {
 		*(.init);
Index: uspace/lib/c/arch/amd64/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/amd64/include/elf_linux.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/amd64/include/elf_linux.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -66,4 +66,16 @@
 	uint64_t rsp;
 	uint64_t ss;
+
+	/*
+	 * The following registers need to be part of elf_regs_t.
+	 * Unfortunately, we don't have any information about them in our
+	 * istate_t.
+	 */
+	uint64_t unused_fs_base;
+	uint64_t unused_gs_base;
+	uint64_t unused_ds;
+	uint64_t unused_es;
+	uint64_t unused_fs;
+	uint64_t unused_gs;
 } elf_regs_t;
 
@@ -91,4 +103,14 @@
 	elf_regs->rsp = istate->rsp;
 	elf_regs->ss = istate->ss;
+
+	/*
+	 * Reset the registers for which there is not enough info in istate_t.
+	 */
+	elf_regs->unused_fs_base = 0;
+	elf_regs->unused_gs_base = 0;
+	elf_regs->unused_ds = 0;
+	elf_regs->unused_es = 0;
+	elf_regs->unused_fs = 0;
+	elf_regs->unused_gs = 0;
 }
 
Index: uspace/lib/c/arch/arm32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/arm32/_link.ld.in	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/arm32/_link.ld.in	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -14,12 +14,16 @@
 SECTIONS {
 #ifdef LOADER
+	. = 0x70001000 + SIZEOF_HEADERS;
+	
 	.interp : {
 		*(.interp);
-	} :interp
-	
-	. = 0x70001000 + SIZEOF_HEADERS;
+	} :interp :text
 #else
 	. = 0x1000 + SIZEOF_HEADERS;
 #endif
+	
+	/* Make sure the code is aligned reasonably */
+	. = ALIGN(., 8);
+	
 	.init : {
 		*(.init);
Index: uspace/lib/c/arch/arm32/src/fibril.S
===================================================================
--- uspace/lib/c/arch/arm32/src/fibril.S	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/arm32/src/fibril.S	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -35,5 +35,5 @@
 	stmia r0!, {sp, lr}
 	stmia r0!, {r4-r11}
-
+	
 	# return 1
 	mov r0, #1
@@ -43,6 +43,6 @@
 	ldmia r0!, {sp, lr}
 	ldmia r0!, {r4-r11}
-
-	#return 0
+	
+	# return 0
 	mov r0, #0
 	mov pc, lr
Index: uspace/lib/c/arch/arm32/src/stacktrace_asm.S
===================================================================
--- uspace/lib/c/arch/arm32/src/stacktrace_asm.S	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/arm32/src/stacktrace_asm.S	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -41,4 +41,4 @@
 
 stacktrace_pc_get:
-	mov r0, lr 
+	mov r0, lr
 	mov pc, lr
Index: uspace/lib/c/arch/arm32/src/thread_entry.s
===================================================================
--- uspace/lib/c/arch/arm32/src/thread_entry.s	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/arm32/src/thread_entry.s	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -42,4 +42,4 @@
 	push {fp, ip, lr, pc}
 	sub fp, ip, #4
-
-        b __thread_main
+	
+	b __thread_main
Index: uspace/lib/c/arch/ia32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ia32/_link.ld.in	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/ia32/_link.ld.in	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -19,9 +19,4 @@
 
 SECTIONS {
-#if defined(LOADER) || defined(DLEXE)
-	.interp : {
-		*(.interp);
-	} :interp
-#endif
 #ifdef LOADER
 	. = 0x70001000 + SIZEOF_HEADERS;
@@ -29,4 +24,14 @@
 	. = 0x1000 + SIZEOF_HEADERS;
 #endif
+	
+#if defined(LOADER) || defined(DLEXE)
+	.interp : {
+		*(.interp);
+	} :interp :text
+#endif
+	
+	/* Make sure the code is aligned reasonably */
+	. = ALIGN(., 16);
+	
 	.init : {
 		*(.init);
@@ -37,5 +42,5 @@
 		*(.rodata .rodata.*);
 	} :text
-
+	
 #if defined(SHLIB) || defined(DLEXE)
 	.rel.plt : {
@@ -80,12 +85,13 @@
 #if defined(SHLIB) || defined(DLEXE)
 	.data.rel : {
-                *(.data.rel .data.rel.*);
+		*(.data.rel .data.rel.*);
 	} :data
-
+	
 	.got : {
-                *(.got);
+		*(.got);
 	} :data
+	
 	.got.plt : {
-                *(.got.plt);
+		*(.got.plt);
 	} :data
 #endif
Index: uspace/lib/c/arch/ia64/Makefile.common
===================================================================
--- uspace/lib/c/arch/ia64/Makefile.common	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/ia64/Makefile.common	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -27,5 +27,15 @@
 #
 
-GCC_CFLAGS += -fno-unwind-tables
+#
+# FIXME:
+#
+# The -fno-selective-scheduling and -fno-selective-scheduling2 options
+# should be removed as soon as a bug in GCC concerning unchecked
+# speculative loads is fixed.
+#
+# See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53975 for reference.
+#
+
+GCC_CFLAGS += -fno-unwind-tables -fno-selective-scheduling -fno-selective-scheduling2
 
 ENDIANESS = LE
Index: uspace/lib/c/arch/ia64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ia64/_link.ld.in	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/ia64/_link.ld.in	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -14,18 +14,16 @@
 SECTIONS {
 #ifdef LOADER
+	. = 0x800000000 + SIZEOF_HEADERS;
+	
 	.interp : {
 		*(.interp);
-	} :interp
-	
-	. = 0x800000000 + SIZEOF_HEADERS;
+	} :interp :text
 #else
 	. = 0x4000 + SIZEOF_HEADERS;
 #endif
-	/*
-	 * XXX This is just a work around. Problem: .init section does not
-	 * have the proper alignment.
-	 */
+	
+	/* Make sure the code is aligned reasonably */
 	. = ALIGN(., 16);
-
+	
 	.init : {
 		*(.init);
Index: uspace/lib/c/arch/mips32/Makefile.common
===================================================================
--- uspace/lib/c/arch/mips32/Makefile.common	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/mips32/Makefile.common	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -27,5 +27,5 @@
 #
 
-GCC_CFLAGS += -mips3 -mabi=32
+GCC_CFLAGS += -msoft-float -mips3 -mabi=32
 
 ENDIANESS = LE
Index: uspace/lib/c/arch/mips32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/mips32/_link.ld.in	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/mips32/_link.ld.in	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -14,12 +14,16 @@
 SECTIONS {
 #ifdef LOADER
+	. = 0x70004000 + SIZEOF_HEADERS;
+	
 	.interp : {
 		*(.interp);
-	} :interp
-	
-	. = 0x70004000 + SIZEOF_HEADERS;
+	} :interp :text
 #else
 	. = 0x4000 + SIZEOF_HEADERS;
 #endif
+	
+	/* Make sure the code is aligned reasonably */
+	. = ALIGN(., 16);
+	
 	.init : {
 		*(.init);
Index: uspace/lib/c/arch/mips32eb/Makefile.common
===================================================================
--- uspace/lib/c/arch/mips32eb/Makefile.common	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/mips32eb/Makefile.common	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -27,5 +27,5 @@
 #
 
-GCC_CFLAGS += -mips3 -mabi=32
+GCC_CFLAGS += -msoft-float -mips3 -mabi=32
 
 ENDIANESS = BE
Index: uspace/lib/c/arch/mips64/Makefile.common
===================================================================
--- uspace/lib/c/arch/mips64/Makefile.common	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/mips64/Makefile.common	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -27,5 +27,5 @@
 #
 
-GCC_CFLAGS += -mips3 -mabi=64
+GCC_CFLAGS += -msoft-float -mips3 -mabi=64
 AFLAGS = -64
 
Index: uspace/lib/c/arch/mips64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/mips64/_link.ld.in	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/mips64/_link.ld.in	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -15,12 +15,16 @@
 SECTIONS {
 #ifdef LOADER
+	. = 0x70004000 + SIZEOF_HEADERS;
+	
 	.interp : {
 		*(.interp);
-	} :interp
-	
-	. = 0x70004000 + SIZEOF_HEADERS;
+	} :interp :text
 #else
 	. = 0x4000 + SIZEOF_HEADERS;
 #endif
+	
+	/* Make sure the code is aligned reasonably */
+	. = ALIGN(., 16);
+	
 	.init : {
 		*(.init);
Index: uspace/lib/c/arch/ppc32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ppc32/_link.ld.in	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/ppc32/_link.ld.in	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -15,12 +15,16 @@
 SECTIONS {
 #ifdef LOADER
+	. = 0x70001000 + SIZEOF_HEADERS;
+	
 	.interp : {
 		*(.interp);
-	} :interp
-	
-	. = 0x70001000 + SIZEOF_HEADERS;
+	} :interp :text
 #else
 	. = 0x1000 + SIZEOF_HEADERS;
 #endif
+	
+	/* Make sure the code is aligned reasonably */
+	. = ALIGN(., 4);
+	
 	.init : {
 		*(.init);
Index: uspace/lib/c/arch/sparc64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/sparc64/_link.ld.in	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/arch/sparc64/_link.ld.in	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -14,12 +14,16 @@
 SECTIONS {
 #ifdef LOADER
+	. = 0x70004000 + SIZEOF_HEADERS;
+	
 	.interp : {
 		*(.interp);
-	} :interp
-	
-	. = 0x70004000 + SIZEOF_HEADERS;
+	} :interp :text
 #else
 	. = 0x4000 + SIZEOF_HEADERS;
 #endif
+	
+	/* Make sure the code is aligned reasonably */
+	. = ALIGN(., 16);
+	
 	.init : {
 		*(.init);
Index: uspace/lib/c/generic/device/ahci.c
===================================================================
--- uspace/lib/c/generic/device/ahci.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/lib/c/generic/device/ahci.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/dev_iface.h>
+#include <assert.h>
+#include <device/ahci.h>
+#include <errno.h>
+#include <async.h>
+#include <ipc/services.h>
+#include <stdio.h>
+#include <as.h>
+
+typedef enum {
+	IPC_M_AHCI_GET_SATA_DEVICE_NAME,
+	IPC_M_AHCI_GET_NUM_BLOCKS,
+	IPC_M_AHCI_GET_BLOCK_SIZE,
+	IPC_M_AHCI_READ_BLOCKS,
+	IPC_M_AHCI_WRITE_BLOCKS,
+} ahci_iface_funcs_t;
+
+#define MAX_NAME_LENGTH  1024
+
+#define LO(ptr) \
+	((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) & 0xffffffff))
+
+#define HI(ptr) \
+	((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) >> 32))
+
+async_sess_t* ahci_get_sess(devman_handle_t funh, char **name)
+{
+	// FIXME: Use a better way than substring match
+	
+	*name = NULL;
+	
+	char devn[MAX_NAME_LENGTH];
+	int rc = devman_fun_get_name(funh, devn, MAX_NAME_LENGTH);
+	if (rc != EOK)
+		return NULL;
+	
+	size_t devn_size = str_size(devn);
+	
+	if ((devn_size > 5) && (str_lcmp(devn, "ahci_", 5) == 0)) {
+		async_sess_t *sess = devman_device_connect(EXCHANGE_PARALLEL,
+		    funh, IPC_FLAG_BLOCKING);
+		
+		if (sess) {
+			*name = str_dup(devn);
+			return sess;
+		}
+	}
+	
+	return NULL;
+}
+
+int ahci_get_sata_device_name(async_sess_t *sess, size_t sata_dev_name_length,
+    char *sata_dev_name)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (!exch)
+		return EINVAL;
+	
+	aid_t req = async_send_2(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
+	    IPC_M_AHCI_GET_SATA_DEVICE_NAME, sata_dev_name_length, NULL);
+	
+	async_data_read_start(exch, sata_dev_name, sata_dev_name_length);
+	
+	sysarg_t rc;
+	async_wait_for(req, &rc);
+	
+	return rc;
+}
+
+int ahci_get_num_blocks(async_sess_t *sess, uint64_t *blocks)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (!exch)
+		return EINVAL;
+	
+	sysarg_t blocks_hi;
+	sysarg_t blocks_lo;
+	int rc = async_req_1_2(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
+	    IPC_M_AHCI_GET_NUM_BLOCKS, &blocks_hi, &blocks_lo);
+	
+	async_exchange_end(exch);
+	
+	if (rc == EOK) {
+		*blocks = (((uint64_t) blocks_hi) << 32)
+		    | (((uint64_t) blocks_lo) & 0xffffffff);
+	}
+	
+	return rc;
+}
+
+int ahci_get_block_size(async_sess_t *sess, size_t *blocks_size)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (!exch)
+		return EINVAL;
+	
+	sysarg_t bs;
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
+	    IPC_M_AHCI_GET_BLOCK_SIZE, &bs);
+	
+	async_exchange_end(exch);
+	
+	if (rc == EOK)
+		*blocks_size = (size_t) bs;
+	
+	return rc;
+}
+
+int ahci_read_blocks(async_sess_t *sess, uint64_t blocknum, size_t count,
+    void *buf)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (!exch)
+		return EINVAL;
+	
+	aid_t req;
+	req = async_send_4(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
+	    IPC_M_AHCI_READ_BLOCKS, HI(blocknum),  LO(blocknum), count, NULL);
+	
+	async_share_out_start(exch, buf, AS_AREA_READ | AS_AREA_WRITE);
+	
+	async_exchange_end(exch);
+	
+	sysarg_t rc;
+	async_wait_for(req, &rc);
+	
+	return rc;
+}
+
+int ahci_write_blocks(async_sess_t *sess, uint64_t blocknum, size_t count,
+    void* buf)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (!exch)
+		return EINVAL;
+	
+	aid_t req = async_send_4(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
+	    IPC_M_AHCI_WRITE_BLOCKS, HI(blocknum),  LO(blocknum), count, NULL);
+	
+	async_share_out_start(exch, buf, AS_AREA_READ | AS_AREA_WRITE);
+	
+	async_exchange_end(exch);
+	
+	sysarg_t rc;
+	async_wait_for(req, &rc);
+	
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/malloc.c
===================================================================
--- uspace/lib/c/generic/malloc.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/generic/malloc.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -109,4 +109,7 @@
 	(((uintptr_t) (area)->end) - sizeof(heap_block_foot_t))
 
+#define AREA_LAST_BLOCK_HEAD(area) \
+	((uintptr_t) BLOCK_HEAD(((heap_block_foot_t *) AREA_LAST_BLOCK_FOOT(area))))
+
 /** Get header in heap block.
  *
@@ -346,8 +349,18 @@
 		return false;
 	
-	/* Add new free block */
-	size_t net_size = (size_t) (end - area->end);
-	if (net_size > 0)
-		block_init(area->end, net_size, true, area);
+	heap_block_head_t *last_head =
+	    (heap_block_head_t *) AREA_LAST_BLOCK_HEAD(area);
+	
+	if (last_head->free) {
+		/* Add the new space to the last block. */
+		size_t net_size = (size_t) (end - area->end) + last_head->size;
+		malloc_assert(net_size > 0);
+		block_init(last_head, net_size, true, area);
+	} else {
+		/* Add new free block */
+		size_t net_size = (size_t) (end - area->end);
+		if (net_size > 0)
+			block_init(area->end, net_size, true, area);
+	}
 	
 	/* Update heap area parameters */
@@ -355,27 +368,4 @@
 	
 	return true;
-}
-
-/** Try to enlarge any of the heap areas
- *
- * Should be called only inside the critical section.
- *
- * @param size Gross size of item to allocate (bytes).
- *
- */
-static bool heap_grow(size_t size)
-{
-	if (size == 0)
-		return true;
-	
-	/* First try to enlarge some existing area */
-	for (heap_area_t *area = first_heap_area; area != NULL;
-	    area = area->next) {
-		if (area_grow(area, size))
-			return true;
-	}
-	
-	/* Eventually try to create a new area */
-	return area_create(AREA_OVERHEAD(size));
 }
 
@@ -661,4 +651,50 @@
 }
 
+/** Try to enlarge any of the heap areas.
+ *
+ * If successful, allocate block of the given size in the area.
+ * Should be called only inside the critical section.
+ *
+ * @param size  Gross size of item to allocate (bytes).
+ * @param align Memory address alignment.
+ *
+ * @return Allocated block.
+ * @return NULL on failure.
+ *
+ */
+static void *heap_grow_and_alloc(size_t size, size_t align)
+{
+	if (size == 0)
+		return NULL;
+	
+	/* First try to enlarge some existing area */
+	for (heap_area_t *area = first_heap_area; area != NULL;
+	    area = area->next) {
+		
+		if (area_grow(area, size + align)) {
+			heap_block_head_t *first =
+			    (heap_block_head_t *) AREA_LAST_BLOCK_HEAD(area);
+			
+			void *addr =
+			    malloc_area(area, first, NULL, size, align);
+			malloc_assert(addr != NULL);
+			return addr;
+		}
+	}
+	
+	/* Eventually try to create a new area */
+	if (area_create(AREA_OVERHEAD(size + align))) {
+		heap_block_head_t *first =
+		    (heap_block_head_t *) AREA_FIRST_BLOCK_HEAD(last_heap_area);
+		
+		void *addr =
+		    malloc_area(last_heap_area, first, NULL, size, align);
+		malloc_assert(addr != NULL);
+		return addr;
+	}
+	
+	return NULL;
+}
+
 /** Allocate a memory block
  *
@@ -679,16 +715,22 @@
 	
 	size_t falign = lcm(align, BASE_ALIGN);
-	size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
-	
-	bool retry = false;
-	heap_block_head_t *split;
-	
-loop:
+	
+	/* Check for integer overflow. */
+	if (falign < align)
+		return NULL;
+	
+	/*
+	 * The size of the allocated block needs to be naturally
+	 * aligned, because the footer structure also needs to reside
+	 * on a naturally aligned address in order to avoid unaligned
+	 * memory accesses.
+	 */
+	size_t gross_size = GROSS_SIZE(ALIGN_UP(size, BASE_ALIGN));
 	
 	/* Try the next fit approach */
-	split = next_fit;
+	heap_block_head_t *split = next_fit;
 	
 	if (split != NULL) {
-		void *addr = malloc_area(split->area, split, NULL, real_size,
+		void *addr = malloc_area(split->area, split, NULL, gross_size,
 		    falign);
 		
@@ -703,5 +745,5 @@
 		    AREA_FIRST_BLOCK_HEAD(area);
 		
-		void *addr = malloc_area(area, first, split, real_size,
+		void *addr = malloc_area(area, first, split, gross_size,
 		    falign);
 		
@@ -710,13 +752,6 @@
 	}
 	
-	if (!retry) {
-		/* Try to grow the heap space */
-		if (heap_grow(real_size)) {
-			retry = true;
-			goto loop;
-		}
-	}
-	
-	return NULL;
+	/* Finally, try to grow heap space and allocate in the new area. */
+	return heap_grow_and_alloc(gross_size, falign);
 }
 
@@ -731,4 +766,6 @@
 void *calloc(const size_t nmemb, const size_t size)
 {
+	// FIXME: Check for overflow
+	
 	void *block = malloc(nmemb * size);
 	if (block == NULL)
@@ -870,5 +907,5 @@
 	if (addr == NULL)
 		return;
-
+	
 	futex_down(&malloc_futex);
 	
Index: uspace/lib/c/generic/str.c
===================================================================
--- uspace/lib/c/generic/str.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/generic/str.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -428,12 +428,17 @@
  *
  * Do a char-by-char comparison of two NULL-terminated strings.
- * The strings are considered equal iff they consist of the same
- * characters on the minimum of their lengths.
+ * The strings are considered equal iff their length is equal
+ * and both strings consist of the same sequence of characters.
+ *
+ * A string S1 is less than another string S2 if it has a character with
+ * lower value at the first character position where the strings differ.
+ * If the strings differ in length, the shorter one is treated as if
+ * padded by characters with a value of zero.
  *
  * @param s1 First string to compare.
  * @param s2 Second string to compare.
  *
- * @return 0 if the strings are equal, -1 if first is smaller,
- *         1 if second smaller.
+ * @return 0 if the strings are equal, -1 if the first is less than the second,
+ *         1 if the second is less than the first.
  *
  */
@@ -466,6 +471,14 @@
  *
  * Do a char-by-char comparison of two NULL-terminated strings.
- * The strings are considered equal iff they consist of the same
- * characters on the minimum of their lengths and the length limit.
+ * The strings are considered equal iff
+ * min(str_length(s1), max_len) == min(str_length(s2), max_len)
+ * and both strings consist of the same sequence of characters,
+ * up to max_len characters.
+ *
+ * A string S1 is less than another string S2 if it has a character with
+ * lower value at the first character position where the strings differ.
+ * If the strings differ in length, the shorter one is treated as if
+ * padded by characters with a value of zero. Only the first max_len
+ * characters are considered.
  *
  * @param s1      First string to compare.
@@ -473,6 +486,6 @@
  * @param max_len Maximum number of characters to consider.
  *
- * @return 0 if the strings are equal, -1 if first is smaller,
- *         1 if second smaller.
+ * @return 0 if the strings are equal, -1 if the first is less than the second,
+ *         1 if the second is less than the first.
  *
  */
@@ -508,4 +521,40 @@
 	return 0;
 
+}
+
+/** Test whether p is a prefix of s.
+ *
+ * Do a char-by-char comparison of two NULL-terminated strings
+ * and determine if p is a prefix of s.
+ *
+ * @param s The string in which to look
+ * @param p The string to check if it is a prefix of s
+ *
+ * @return true iff p is prefix of s else false
+ *
+ */
+bool str_test_prefix(const char *s, const char *p)
+{
+	wchar_t c1 = 0;
+	wchar_t c2 = 0;
+	
+	size_t off1 = 0;
+	size_t off2 = 0;
+
+	while (true) {
+		c1 = str_decode(s, &off1, STR_NO_LIMIT);
+		c2 = str_decode(p, &off2, STR_NO_LIMIT);
+		
+		if (c2 == 0)
+			return true;
+
+		if (c1 != c2)
+			return false;
+		
+		if (c1 == 0)
+			break;
+	}
+
+	return false;
 }
 
@@ -1085,5 +1134,5 @@
 		c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
 		    (c <= '9' ? c - '0' : 0xff)));
-		if (c > base) {
+		if (c >= base) {
 			break;
 		}
Index: uspace/lib/c/include/device/ahci.h
===================================================================
--- uspace/lib/c/include/device/ahci.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/lib/c/include/device/ahci.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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 libc
+ * @{
+ */
+/** @file
+ * @brief AHCI interface definition.
+ */
+
+#ifndef LIBC_DEVICE_AHCI_H_
+#define LIBC_DEVICE_AHCI_H_
+
+#include <async.h>
+#include <devman.h>
+
+extern async_sess_t* ahci_get_sess(devman_handle_t, char **);
+
+extern int ahci_get_sata_device_name(async_sess_t *, size_t, char *);
+extern int ahci_get_num_blocks(async_sess_t *, uint64_t *);
+extern int ahci_get_block_size(async_sess_t *, size_t *);
+extern int ahci_read_blocks(async_sess_t *, uint64_t, size_t, void *);
+extern int ahci_write_blocks(async_sess_t *, uint64_t, size_t, void *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ipc/dev_iface.h
===================================================================
--- uspace/lib/c/include/ipc/dev_iface.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -51,4 +51,6 @@
 	/** Interface provided by USB HID devices. */
 	USBHID_DEV_IFACE,
+	/** Interface provided by AHCI devices. */
+	AHCI_DEV_IFACE,
 
 	DEV_IFACE_MAX
Index: uspace/lib/c/include/str.h
===================================================================
--- uspace/lib/c/include/str.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/c/include/str.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -79,4 +79,6 @@
 extern int str_lcmp(const char *s1, const char *s2, size_t max_len);
 
+extern bool str_test_prefix(const char *s, const char *p);
+
 extern void str_cpy(char *dest, size_t size, const char *src);
 extern void str_ncpy(char *dest, size_t size, const char *src, size_t n);
Index: uspace/lib/clui/tinput.c
===================================================================
--- uspace/lib/clui/tinput.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/clui/tinput.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -601,5 +601,9 @@
 	
 	unsigned int cols = max(1, (ti->con_cols + 1) / (max_length + 1));
-	unsigned int col_width = ti->con_cols / cols;
+	unsigned int padding = 0;
+	if ((cols * max_length) + (cols - 1) < ti->con_cols) {
+		padding = ti->con_cols - (cols * max_length) - (cols - 1);
+	}
+	unsigned int col_width = max_length + padding / cols;
 	unsigned int rows = cnum / cols + ((cnum % cols) != 0);
 	
Index: uspace/lib/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/drv/Makefile	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -44,5 +44,6 @@
 	generic/remote_pci.c \
 	generic/remote_usbhc.c \
-	generic/remote_usbhid.c
+	generic/remote_usbhid.c \
+	generic/remote_ahci.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/drv/generic/dev_iface.c
===================================================================
--- uspace/lib/drv/generic/dev_iface.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/drv/generic/dev_iface.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -46,4 +46,5 @@
 #include "remote_usbhid.h"
 #include "remote_pci.h"
+#include "remote_ahci.h"
 
 static iface_dipatch_table_t remote_ifaces = {
@@ -55,5 +56,6 @@
 		&remote_usb_iface,
 		&remote_usbhc_iface,
-		&remote_usbhid_iface
+		&remote_usbhid_iface,
+		&remote_ahci_iface
 	}
 };
Index: uspace/lib/drv/generic/remote_ahci.c
===================================================================
--- uspace/lib/drv/generic/remote_ahci.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/lib/drv/generic/remote_ahci.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,208 @@
+/*
+  * Copyright (c) 2012 Petr Jerman
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <stdio.h>
+#include "ahci_iface.h"
+#include "ddf/driver.h"
+
+typedef enum {
+	IPC_M_AHCI_GET_SATA_DEVICE_NAME,
+	IPC_M_AHCI_GET_NUM_BLOCKS,
+	IPC_M_AHCI_GET_BLOCK_SIZE,
+	IPC_M_AHCI_READ_BLOCKS,
+	IPC_M_AHCI_WRITE_BLOCKS
+} ahci_iface_funcs_t;
+
+#define LO(ptr) \
+	((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) & 0xffffffff))
+
+#define HI(ptr) \
+	((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) >> 32))
+
+static void remote_ahci_get_sata_device_name(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+static void remote_ahci_get_num_blocks(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+static void remote_ahci_get_block_size(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+static void remote_ahci_read_blocks(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+static void remote_ahci_write_blocks(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+
+/** Remote AHCI interface operations. */
+static remote_iface_func_ptr_t remote_ahci_iface_ops [] = {
+	[IPC_M_AHCI_GET_SATA_DEVICE_NAME] = remote_ahci_get_sata_device_name,
+	[IPC_M_AHCI_GET_NUM_BLOCKS] = remote_ahci_get_num_blocks,
+	[IPC_M_AHCI_GET_BLOCK_SIZE] = remote_ahci_get_block_size,
+	[IPC_M_AHCI_READ_BLOCKS] = remote_ahci_read_blocks,
+	[IPC_M_AHCI_WRITE_BLOCKS] = remote_ahci_write_blocks
+};
+
+/** Remote AHCI interface structure.
+ */
+remote_iface_t remote_ahci_iface = {
+	.method_count = sizeof(remote_ahci_iface_ops) /
+	    sizeof(remote_ahci_iface_ops[0]),
+	.methods = remote_ahci_iface_ops
+};
+
+void remote_ahci_get_sata_device_name(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
+	
+	if (ahci_iface->get_sata_device_name == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	const size_t sata_dev_name_length =
+	    (size_t) DEV_IPC_GET_ARG1(*call);
+	
+	char* sata_dev_name = malloc(sata_dev_name_length);
+	
+	const int ret = ahci_iface->get_sata_device_name(fun,
+	    sata_dev_name_length, sata_dev_name);
+	
+	size_t real_size;
+	ipc_callid_t cid;
+	if ((async_data_read_receive(&cid, &real_size)) &&
+	    (real_size == sata_dev_name_length))
+		async_data_read_finalize(cid, sata_dev_name, sata_dev_name_length);
+	
+	async_answer_0(callid, ret);
+}
+
+static void remote_ahci_get_num_blocks(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
+	
+	if (ahci_iface->get_num_blocks == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	uint64_t blocks;
+	const int ret = ahci_iface->get_num_blocks(fun, &blocks);
+	
+	if (ret != EOK)
+		async_answer_0(callid, ret);
+	else
+		async_answer_2(callid, EOK, HI(blocks), LO(blocks));
+}
+
+static void remote_ahci_get_block_size(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
+	
+	if (ahci_iface->get_block_size == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	size_t blocks;
+	const int ret = ahci_iface->get_block_size(fun, &blocks);
+	
+	if (ret != EOK)
+		async_answer_0(callid, ret);
+	else
+		async_answer_1(callid, EOK, blocks);
+}
+
+void remote_ahci_read_blocks(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
+	
+	if (ahci_iface->read_blocks == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	size_t maxblock_size;
+	unsigned int flags;
+	
+	ipc_callid_t cid;
+	async_share_out_receive(&cid, &maxblock_size, &flags);
+	
+	void *buf;
+	async_share_out_finalize(cid, &buf);
+	
+	const uint64_t blocknum =
+	    (((uint64_t) (DEV_IPC_GET_ARG1(*call))) << 32) |
+	    (((uint64_t) (DEV_IPC_GET_ARG2(*call))) & 0xffffffff);
+	const size_t cnt = (size_t) DEV_IPC_GET_ARG3(*call);
+	
+	const int ret = ahci_iface->read_blocks(fun, blocknum, cnt, buf);
+	
+	async_answer_0(callid, ret);
+}
+
+void remote_ahci_write_blocks(ddf_fun_t *fun, void *iface, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
+	
+	if (ahci_iface->read_blocks == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	size_t maxblock_size;
+	unsigned int flags;
+	
+	ipc_callid_t cid;
+	async_share_out_receive(&cid, &maxblock_size, &flags);
+	
+	void *buf;
+	async_share_out_finalize(cid, &buf);
+	
+	const uint64_t blocknum =
+	    (((uint64_t)(DEV_IPC_GET_ARG1(*call))) << 32) |
+	    (((uint64_t)(DEV_IPC_GET_ARG2(*call))) & 0xffffffff);
+	const size_t cnt = (size_t) DEV_IPC_GET_ARG3(*call);
+	
+	const int ret = ahci_iface->write_blocks(fun, blocknum, cnt, buf);
+	
+	async_answer_0(callid, ret);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/generic/remote_usb.c
===================================================================
--- uspace/lib/drv/generic/remote_usb.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/drv/generic/remote_usb.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -56,5 +56,5 @@
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	sysarg_t addr;
 	const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
@@ -65,5 +65,5 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Tell interface number given device can use.
  * @param[in] exch IPC communication exchange
@@ -75,5 +75,5 @@
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	sysarg_t iface_no;
 	const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
@@ -83,5 +83,5 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Tell devman handle of device host controller.
  * @param[in] exch IPC communication exchange
@@ -92,5 +92,5 @@
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	devman_handle_t h;
 	const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
@@ -121,5 +121,5 @@
 };
 
-/*----------------------------------------------------------------------------*/
+
 void remote_usb_get_my_address(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -140,5 +140,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -159,5 +159,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usb_get_hc_handle(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -165,5 +165,5 @@
 {
 	if (!exch || !address)
-		return EINVAL;
+		return EBADMEM;
 	sysarg_t new_address;
 	const int ret = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
@@ -173,19 +173,19 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_bind_address(async_exch_t *exch, usb_address_t address,
     devman_handle_t handle)
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	return async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
 	    IPC_M_USBHC_BIND_ADDRESS, address, handle);
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_get_handle(async_exch_t *exch, usb_address_t address,
     devman_handle_t *handle)
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	sysarg_t h;
 	const int ret = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
@@ -195,13 +195,13 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_release_address(async_exch_t *exch, usb_address_t address)
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
 	    IPC_M_USBHC_RELEASE_ADDRESS, address);
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_register_endpoint(async_exch_t *exch, usb_address_t address,
     usb_endpoint_t endpoint, usb_transfer_type_t type,
@@ -209,5 +209,5 @@
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	const usb_target_t target =
 	    {{ .address = address, .endpoint = endpoint }};
@@ -220,23 +220,24 @@
 #undef _PACK2
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_unregister_endpoint(async_exch_t *exch, usb_address_t address,
     usb_endpoint_t endpoint, usb_direction_t direction)
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
 	    IPC_M_USBHC_UNREGISTER_ENDPOINT, address, endpoint, direction);
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_read(async_exch_t *exch, usb_address_t address,
     usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size,
     size_t *rec_size)
 {
+	if (!exch)
+		return EBADMEM;
+
 	if (size == 0 && setup == 0)
 		return EOK;
 
-	if (!exch)
-		return EINVAL;
 	const usb_target_t target =
 	    {{ .address = address, .endpoint = endpoint }};
@@ -284,13 +285,14 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_write(async_exch_t *exch, usb_address_t address,
     usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size)
 {
+	if (!exch)
+		return EBADMEM;
+
 	if (size == 0 && setup == 0)
 		return EOK;
 
-	if (!exch)
-		return EINVAL;
 	const usb_target_t target =
 	    {{ .address = address, .endpoint = endpoint }};
@@ -319,5 +321,5 @@
 	return (int) opening_request_rc;
 }
-/*----------------------------------------------------------------------------*/
+
 
 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
@@ -384,5 +386,5 @@
 	return trans;
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -406,5 +408,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -423,5 +425,5 @@
 	async_answer_0(callid, ret);
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usbhc_get_handle(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -444,5 +446,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usbhc_release_address(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -460,5 +462,5 @@
 	async_answer_0(callid, ret);
 }
-/*----------------------------------------------------------------------------*/
+
 static void callback_out(ddf_fun_t *fun,
     int outcome, void *arg)
@@ -470,5 +472,5 @@
 	async_transaction_destroy(trans);
 }
-/*----------------------------------------------------------------------------*/
+
 static void callback_in(ddf_fun_t *fun,
     int outcome, size_t actual_size, void *arg)
@@ -494,5 +496,5 @@
 	async_transaction_destroy(trans);
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -594,5 +596,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usbhc_write(
     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
Index: uspace/lib/drv/include/ahci_iface.h
===================================================================
--- uspace/lib/drv/include/ahci_iface.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/lib/drv/include/ahci_iface.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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 libdrv
+ * @addtogroup ahci
+ * @{
+ */
+/** @file
+ * @brief AHCI interface definition.
+ */
+
+#ifndef LIBDRV_AHCI_IFACE_H_
+#define LIBDRV_AHCI_IFACE_H_
+
+#include "ddf/driver.h"
+#include <async.h>
+
+/** AHCI device communication interface. */
+typedef struct {
+	int (*get_sata_device_name)(ddf_fun_t *, size_t, char *);
+	int (*get_num_blocks)(ddf_fun_t *, uint64_t *);
+	int (*get_block_size)(ddf_fun_t *, size_t *);
+	int (*read_blocks)(ddf_fun_t *, uint64_t, size_t, void *);
+	int (*write_blocks)(ddf_fun_t *, uint64_t, size_t, void *);
+} ahci_iface_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/remote_ahci.h
===================================================================
--- uspace/lib/drv/include/remote_ahci.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/lib/drv/include/remote_ahci.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_AHCI_H_
+#define LIBDRV_REMOTE_AHCI_H_
+
+extern remote_iface_t remote_ahci_iface;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/include/usb/dev/usb_device_connection.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/usb_device_connection.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbdev/include/usb/dev/usb_device_connection.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -72,5 +72,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Register endpoint on the device.
  * @param instance device connection structure to use.
@@ -91,5 +91,5 @@
 	    instance->address, ep, type, direction, packet_size, interval);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Unregister endpoint on the device.
  * @param instance device connection structure
@@ -105,5 +105,5 @@
 	    instance->address, ep, dir);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Get data from the device.
  * @param[in] instance device connection structure to use.
@@ -122,5 +122,5 @@
 	    instance->address, ep, setup, data, size, rsize);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Send data to the device.
  * @param instance device connection structure to use.
@@ -138,5 +138,5 @@
 	    instance->address, ep, setup, data, size);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Wrapper for read calls with no setup stage.
  * @param[in] instance device connection structure.
@@ -153,5 +153,5 @@
 	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.
Index: uspace/lib/usbdev/src/devdrv.c
===================================================================
--- uspace/lib/usbdev/src/devdrv.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbdev/src/devdrv.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -74,5 +74,5 @@
 	return ddf_driver_main(&generic_driver);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Count number of pipes the driver expects.
  *
@@ -87,5 +87,5 @@
 	return count;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback when a new device is supposed to be controlled by this driver.
  *
@@ -124,5 +124,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback when a device is supposed to be removed from the system.
  *
@@ -146,5 +146,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback when a device was removed from the system.
  *
@@ -167,5 +167,5 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Destroy existing pipes of a USB device.
  *
@@ -178,5 +178,5 @@
 	dev->pipes_count = 0;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Change interface setting of a device.
  * This function selects new alternate setting of an interface by issuing
Index: uspace/lib/usbdev/src/pipes.c
===================================================================
--- uspace/lib/usbdev/src/pipes.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbdev/src/pipes.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -54,5 +54,5 @@
 	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.
@@ -67,5 +67,5 @@
 	return usb_hc_connection_close(pipe->wire->hc_connection);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Try to clear endpoint halt of default control pipe.
  *
@@ -85,5 +85,5 @@
 	pipe->auto_reset_halt = true;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Request a control read transfer on an endpoint pipe.
  *
@@ -135,5 +135,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Request a control write transfer on an endpoint pipe.
  *
@@ -182,5 +182,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Request a read (in) transfer on an endpoint pipe.
  *
@@ -227,5 +227,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Request a write (out) transfer on an endpoint pipe.
  *
@@ -259,5 +259,5 @@
 	    pipe->endpoint_no, buffer, size);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize USB endpoint pipe.
  *
@@ -287,5 +287,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize USB endpoint pipe as the default zero control pipe.
  *
@@ -307,5 +307,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Register endpoint with the host controller.
  *
@@ -323,5 +323,5 @@
 	   pipe->direction, pipe->max_packet_size, interval);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Revert endpoint registration with the host controller.
  *
Index: uspace/lib/usbdev/src/pipesinit.c
===================================================================
--- uspace/lib/usbdev/src/pipesinit.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbdev/src/pipesinit.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -154,5 +154,5 @@
     usb_endpoint_mapping_t *mapping, size_t mapping_count,
     usb_standard_interface_descriptor_t *interface,
-    usb_standard_endpoint_descriptor_t *endpoint,
+    usb_standard_endpoint_descriptor_t *endpoint_desc,
     usb_device_connection_t *wire)
 {
@@ -163,13 +163,13 @@
 
 	/* Actual endpoint number is in bits 0..3 */
-	const usb_endpoint_t ep_no = endpoint->endpoint_address & 0x0F;
+	const usb_endpoint_t ep_no = endpoint_desc->endpoint_address & 0x0F;
 
 	const usb_endpoint_description_t description = {
 		/* Endpoint direction is set by bit 7 */
-		.direction = (endpoint->endpoint_address & 128)
+		.direction = (endpoint_desc->endpoint_address & 128)
 		    ? USB_DIRECTION_IN : USB_DIRECTION_OUT,
 		/* Transfer type is in bits 0..2 and
 		 * the enum values corresponds 1:1 */
-		.transfer_type = endpoint->attributes & 3,
+		.transfer_type = endpoint_desc->attributes & 3,
 
 		/* Get interface characteristics. */
@@ -194,5 +194,6 @@
 
 	int rc = usb_pipe_initialize(&ep_mapping->pipe, wire,
-	    ep_no, description.transfer_type, endpoint->max_packet_size,
+	    ep_no, description.transfer_type,
+	    uint16_usb2host(endpoint_desc->max_packet_size),
 	    description.direction);
 	if (rc != EOK) {
@@ -201,5 +202,5 @@
 
 	ep_mapping->present = true;
-	ep_mapping->descriptor = endpoint;
+	ep_mapping->descriptor = endpoint_desc;
 	ep_mapping->interface = interface;
 
Index: uspace/lib/usbdev/src/request.c
===================================================================
--- uspace/lib/usbdev/src/request.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbdev/src/request.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -114,5 +114,5 @@
   * 	(in native endianness).
   * @param actual_data_size Actual size of transfered data
-  * 	(in native endianness).
+  *        (in native endianness).
   * @return Error code.
   * @retval EBADMEM @p pipe is NULL.
@@ -147,7 +147,7 @@
 		    | (request_type << 5) | recipient,
 		.request = request,
-		.value = value,
-		.index = index,
-		.length = (uint16_t) data_size,
+		.value = uint16_host2usb(value),
+		.index = uint16_host2usb(index),
+		.length = uint16_host2usb(data_size),
 	};
 
@@ -375,5 +375,5 @@
 	usb_standard_device_descriptor_t descriptor_tmp;
 	int rc = usb_request_get_descriptor(pipe,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE, 
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
 	    USB_DESCTYPE_DEVICE, 0, 0,
 	    &descriptor_tmp, sizeof(descriptor_tmp),
@@ -435,5 +435,4 @@
 	/* Everything is okay, copy the descriptor. */
 	memcpy(descriptor, &descriptor_tmp, sizeof(descriptor_tmp));
-
 	return EOK;
 }
@@ -495,9 +494,11 @@
 		return ENOENT;
 	}
-	if (bare_config.total_length < sizeof(bare_config)) {
+
+	const size_t total_length = uint16_usb2host(bare_config.total_length);
+	if (total_length < sizeof(bare_config)) {
 		return ELIMIT;
 	}
 
-	void *buffer = malloc(bare_config.total_length);
+	void *buffer = malloc(total_length);
 	if (buffer == NULL) {
 		return ENOMEM;
@@ -506,5 +507,5 @@
 	size_t transferred = 0;
 	rc = usb_request_get_full_configuration_descriptor(pipe, index,
-	    buffer, bare_config.total_length, &transferred);
+	    buffer, total_length, &transferred);
 	if (rc != EOK) {
 		free(buffer);
@@ -512,5 +513,5 @@
 	}
 
-	if (transferred != bare_config.total_length) {
+	if (transferred != total_length) {
 		free(buffer);
 		return ELIMIT;
@@ -522,5 +523,5 @@
 
 	if (descriptor_size != NULL) {
-		*descriptor_size = bare_config.total_length;
+		*descriptor_size = total_length;
 	}
 
Index: uspace/lib/usbhid/include/usb/hid/hid_report_items.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hid_report_items.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbhid/include/usb/hid/hid_report_items.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -38,5 +38,5 @@
 #include <stdint.h>
 
-/*---------------------------------------------------------------------------*/
+
 /*
  * Item prefix
@@ -56,5 +56,5 @@
 #define USB_HID_ITEM_IS_LONG(data)	(data == 0xFE)
 
-/*---------------------------------------------------------------------------*/
+
 /*
  * Extended usage macros
@@ -70,5 +70,5 @@
 #define USB_HID_EXTENDED_USAGE(usage)		(usage & 0xFFFF)
 
-/*---------------------------------------------------------------------------*/
+
 /*
  * Input/Output/Feature Item flags
@@ -142,5 +142,5 @@
 #define USB_HID_ITEM_FLAG_BUFFERED(flags)	((flags & 0x100) == 0x100)
 
-/*---------------------------------------------------------------------------*/
+
 
 /* MAIN ITEMS */
@@ -185,5 +185,5 @@
 #define USB_HID_REPORT_TAG_END_COLLECTION	0xC
 
-/*---------------------------------------------------------------------------*/
+
 
 /* GLOBAL ITEMS */
@@ -272,5 +272,5 @@
 #define USB_HID_REPORT_TAG_POP			0xB
 
-/*---------------------------------------------------------------------------*/
+
 
 /* LOCAL ITEMS */
@@ -347,5 +347,5 @@
 #define USB_HID_REPORT_TAG_DELIMITER		0xA
 
-/*---------------------------------------------------------------------------*/
+
 
 #endif
Index: uspace/lib/usbhid/include/usb/hid/hidpath.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hidpath.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbhid/include/usb/hid/hidpath.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -41,5 +41,5 @@
 
 
-/*---------------------------------------------------------------------------*/
+
 /*
  * Flags of usage paths comparison modes.
@@ -73,5 +73,5 @@
 #define USB_HID_PATH_COMPARE_ANYWHERE		8
 
-/*----------------------------------------------------------------------------*/
+
 /** 
  * Item of usage path structure. Last item of linked list describes one item
@@ -93,5 +93,5 @@
 
 
-/*---------------------------------------------------------------------------*/
+
 /** 
  * USB HID usage path structure.
@@ -112,5 +112,5 @@
 } usb_hid_report_path_t;
 
-/*---------------------------------------------------------------------------*/
+
 usb_hid_report_path_t *usb_hid_report_path(void);
 
Index: uspace/lib/usbhid/include/usb/hid/hidtypes.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hidtypes.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbhid/include/usb/hid/hidtypes.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -39,5 +39,5 @@
 #include <adt/list.h>
 
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -69,5 +69,5 @@
 	(((x) < 0 ) ? ((1 << (size)) + (x)) : (x))
 
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -86,5 +86,5 @@
 } usb_hid_report_type_t;
 
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -111,5 +111,5 @@
 	
 } usb_hid_report_t;
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -135,5 +135,5 @@
 	link_t reports_link;
 } usb_hid_report_description_t;
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -202,5 +202,5 @@
 } usb_hid_report_field_t;
 
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -287,5 +287,5 @@
 	int in_delimiter;
 } usb_hid_report_item_t;
-/*---------------------------------------------------------------------------*/
+
 /**
  * Enum of the keyboard modifiers 
@@ -314,5 +314,5 @@
 	USB_HID_MOD_RGUI
 };
-/*---------------------------------------------------------------------------*/
+
 
 
Index: uspace/lib/usbhid/include/usb/hid/request.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/request.h	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbhid/include/usb/hid/request.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -42,5 +42,5 @@
 #include <usb/dev/pipes.h>
 
-/*----------------------------------------------------------------------------*/
+
 
 int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no,
@@ -61,5 +61,5 @@
 int usbhid_req_get_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t *duration);
 
-/*----------------------------------------------------------------------------*/
+
 
 #endif /* USB_KBD_HIDREQ_H_ */
Index: uspace/lib/usbhid/src/hiddescriptor.c
===================================================================
--- uspace/lib/usbhid/src/hiddescriptor.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbhid/src/hiddescriptor.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -41,5 +41,5 @@
 #include <assert.h>
 
-/*---------------------------------------------------------------------------*/
+
 /*
  * Constants defining current parsing mode for correct parsing of the set of
@@ -61,5 +61,5 @@
 #define INSIDE_DELIMITER_SET	2
 
-/*---------------------------------------------------------------------------*/
+
 	
 /** The new report item flag. Used to determine when the item is completly
@@ -78,5 +78,5 @@
 #define USB_HID_UNKNOWN_TAG		-99
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Checks if given collection path is already present in report structure and
@@ -124,5 +124,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Initialize the report descriptor parser structure
@@ -147,5 +147,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -314,5 +314,5 @@
 	return EOK;
 }
-/*---------------------------------------------------------------------------*/
+
 /**
  * Finds description of report with given report_id and of given type in
@@ -348,5 +348,5 @@
 	return NULL;
 }
-/*---------------------------------------------------------------------------*/
+
 
 /** Parse HID report descriptor.
@@ -536,5 +536,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -871,5 +871,5 @@
 	return EOK;
 }
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -892,5 +892,5 @@
 	return result;
 }
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -941,5 +941,5 @@
 
 }
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -972,5 +972,5 @@
 	}
 }
-/*---------------------------------------------------------------------------*/
+
 
 
@@ -1022,5 +1022,5 @@
 	return;
 }
-/*---------------------------------------------------------------------------*/
+
 
 /**
Index: uspace/lib/usbhid/src/hidparser.c
===================================================================
--- uspace/lib/usbhid/src/hidparser.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbhid/src/hidparser.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -41,5 +41,5 @@
 #include <assert.h>
 
-/*---------------------------------------------------------------------------*/
+
 /*
  * Data translation private functions
@@ -52,5 +52,5 @@
 	int32_t value);
 
-/*---------------------------------------------------------------------------*/
+
 
 static int usb_pow(int a, int b)
@@ -68,5 +68,5 @@
 	}
 }
-/*---------------------------------------------------------------------------*/
+
 
 /** Returns size of report of specified report id and type in items
@@ -117,5 +117,5 @@
 	}
 }
-/*---------------------------------------------------------------------------*/
+
 
 /** Parse and act upon a HID report.
@@ -192,5 +192,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Translate data from the report as specified in report descriptor item
@@ -274,5 +274,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /* OUTPUT API */
 
@@ -431,5 +431,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Translate given data for putting them into the outoput report
@@ -476,5 +476,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Clones given state table
@@ -497,5 +497,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Function for sequence walking through the report. Returns next field in the
@@ -552,5 +552,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Returns next report_id of report of specified type. If zero is given than
@@ -600,5 +600,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Reset all local items in given state table
Index: uspace/lib/usbhid/src/hidpath.c
===================================================================
--- uspace/lib/usbhid/src/hidpath.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbhid/src/hidpath.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -41,5 +41,5 @@
 #include <assert.h>
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Compares two usages if they are same or not or one of the usages is not
@@ -63,5 +63,5 @@
 	((page1 == page2) || (page1 == 0) || (page2 == 0))
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Appends one item (couple of usage_path and usage) into the usage path
@@ -93,5 +93,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Removes last item from the usage path structure
@@ -114,5 +114,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Nulls last item of the usage path structure.
@@ -133,5 +133,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Modifies last item of usage path structure by given usage page or usage
@@ -164,5 +164,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  *
@@ -188,5 +188,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Compares two usage paths structures
@@ -354,5 +354,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Allocates and initializes new usage path structure.
@@ -376,5 +376,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Releases given usage path structure.
@@ -395,5 +395,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Clone content of given usage path to the new one
@@ -441,5 +441,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Sets report id in usage path structure
Index: uspace/lib/usbhid/src/hidreport.c
===================================================================
--- uspace/lib/usbhid/src/hidreport.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbhid/src/hidreport.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -50,5 +50,5 @@
 #include <usb/hid/hidreport.h>
 
-static int usb_hid_get_report_descriptor(usb_device_t *dev, 
+static int usb_hid_get_report_descriptor(usb_device_t *dev,
     uint8_t **report_desc, size_t *size)
 {
@@ -69,6 +69,6 @@
 	 * First nested descriptor of the configuration descriptor.
 	 */
-	const uint8_t *d = 
-	    usb_dp_get_nested_descriptor(&parser, &parser_data, 
+	const uint8_t *d =
+	    usb_dp_get_nested_descriptor(&parser, &parser_data,
 	    dev->descriptors.configuration);
 	
@@ -78,5 +78,5 @@
 	int i = 0;
 	while (d != NULL && i < dev->interface_no) {
-		d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
+		d = usb_dp_get_sibling_descriptor(&parser, &parser_data,
 		    dev->descriptors.configuration, d);
 		++i;
@@ -99,5 +99,5 @@
 	 */
 	while (d != NULL && *(d + 1) != USB_DESCTYPE_HID) {
-		d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
+		d = usb_dp_get_sibling_descriptor(&parser, &parser_data,
 		    iface_desc, d);
 	}
@@ -114,8 +114,8 @@
 	}
 	
-	usb_standard_hid_descriptor_t *hid_desc = 
+	usb_standard_hid_descriptor_t *hid_desc =
 	    (usb_standard_hid_descriptor_t *)d;
 	
-	uint16_t length =  hid_desc->report_desc_info.length;
+	uint16_t length = uint16_usb2host(hid_desc->report_desc_info.length);
 	size_t actual_size = 0;
 
@@ -161,5 +161,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 
 int usb_hid_process_report_descriptor(usb_device_t *dev, 
Index: uspace/lib/usbhid/src/hidreq.c
===================================================================
--- uspace/lib/usbhid/src/hidreq.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbhid/src/hidreq.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -45,5 +45,5 @@
 #include <usb/hid/request.h>
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Send Set Report request to the HID device.
@@ -97,5 +97,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Send Set Protocol request to the HID device.
@@ -145,5 +145,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Send Set Idle request to the HID device.
@@ -195,5 +195,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Send Get Report request to the HID device.
@@ -251,5 +251,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Send Get Protocol request to the HID device.
@@ -310,5 +310,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Send Get Idle request to the HID device.
@@ -373,5 +373,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 
 /**
Index: uspace/lib/usbhost/src/endpoint.c
===================================================================
--- uspace/lib/usbhost/src/endpoint.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbhost/src/endpoint.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -72,5 +72,5 @@
 	return instance;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Properly dispose of endpoint_t structure.
  * @param instance endpoint_t structure.
@@ -84,5 +84,5 @@
 	free(instance);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Set device specific data and hooks.
  * @param instance endpoint_t structure.
@@ -101,5 +101,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Clear device specific data and hooks.
  * @param instance endpoint_t structure.
@@ -115,5 +115,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Mark the endpoint as active and block access for further fibrils.
  * @param instance endpoint_t structure.
@@ -128,5 +128,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Mark the endpoint as inactive and allow access for further fibrils.
  * @param instance endpoint_t structure.
@@ -140,5 +140,5 @@
 	fibril_condvar_signal(&instance->avail);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Get the value of toggle bit.
  * @param instance endpoint_t structure.
@@ -156,5 +156,5 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Set the value of toggle bit.
  * @param instance endpoint_t structure.
Index: uspace/lib/usbhost/src/usb_device_manager.c
===================================================================
--- uspace/lib/usbhost/src/usb_device_manager.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbhost/src/usb_device_manager.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -61,5 +61,5 @@
 	return new_address;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize device manager structure.
  *
@@ -82,5 +82,5 @@
 	fibril_mutex_initialize(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Request USB address.
  * @param instance usb_device_manager
@@ -124,5 +124,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Bind USB address to devman handle.
  *
@@ -156,5 +156,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Release used USB address.
  *
@@ -182,5 +182,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Find USB address associated with the device.
  *
@@ -205,5 +205,5 @@
 	return ENOENT;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Find devman handle and speed assigned to USB address.
  *
Index: uspace/lib/usbhost/src/usb_endpoint_manager.c
===================================================================
--- uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -61,5 +61,5 @@
 	    && (address == ep->address);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Get list that holds endpoints for given address.
  * @param instance usb_endpoint_manager structure, non-null.
@@ -73,5 +73,5 @@
 	return &instance->endpoint_lists[addr % ENDPOINT_LIST_COUNT];
 }
-/*----------------------------------------------------------------------------*/
+
 /** Internal search function, works on locked structure.
  * @param instance usb_endpoint_manager structure, non-null.
@@ -97,5 +97,5 @@
 	return NULL;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Calculate bandwidth that needs to be reserved for communication with EP.
  * Calculation follows USB 1.1 specification.
@@ -145,5 +145,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize to default state.
  * You need to provide valid bw_count function if you plan to use
@@ -168,5 +168,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Check setup packet data for signs of toggle reset.
  *
@@ -227,5 +227,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Register endpoint structure.
  * Checks for duplicates.
@@ -262,5 +262,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Unregister endpoint structure.
  * Checks for duplicates.
@@ -286,5 +286,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Find endpoint_t representing the given communication route.
  * @param instance usb_endpoint_manager, non-null.
@@ -301,5 +301,5 @@
 	return ep;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Create and register new endpoint_t structure.
  * @param instance usb_endpoint_manager structure, non-null.
@@ -364,5 +364,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Unregister and destroy endpoint_t structure representing given route.
  * @param instance usb_endpoint_manager structure, non-null.
@@ -395,5 +395,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Unregister and destroy all endpoints using given address.
  * @param instance usb_endpoint_manager structure, non-null.
Index: uspace/lib/usbhost/src/usb_transfer_batch.c
===================================================================
--- uspace/lib/usbhost/src/usb_transfer_batch.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/lib/usbhost/src/usb_transfer_batch.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -96,5 +96,5 @@
 	return instance;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Correctly dispose all used data structures.
  *
@@ -116,5 +116,5 @@
 	free(instance);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Prepare data and call the right callback.
  *
Index: uspace/srv/bd/sata_bd/Makefile
===================================================================
--- uspace/srv/bd/sata_bd/Makefile	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/srv/bd/sata_bd/Makefile	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2012 Petr Jerman
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+BINARY = sata_bd
+
+SOURCES = \
+	sata_bd.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/bd/sata_bd/sata_bd.c
===================================================================
--- uspace/srv/bd/sata_bd/sata_bd.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/srv/bd/sata_bd/sata_bd.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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 bd
+ * @{
+ */
+
+/**
+ * @file
+ * @brief SATA disk driver
+ *
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ipc/bd.h>
+#include <str.h>
+#include <loc.h>
+#include <macros.h>
+
+#include <device/ahci.h>
+#include "sata_bd.h"
+
+#define NAME       "sata_bd"
+#define NAMESPACE  "bd"
+
+/** Maximum number of disks handled */
+#define MAXDISKS  256
+
+static sata_bd_dev_t disk[MAXDISKS];
+static int disk_count;
+
+/** Find SATA devices in device tree.
+ *
+ *  @param Device manager handle describing container for searching.  
+ *
+ *  @return EOK if succeed, error code otherwise.
+ *
+ */
+static int scan_device_tree(devman_handle_t funh)
+{
+	devman_handle_t devh;
+	devman_handle_t *cfuns;
+	size_t count, i;
+	int rc;
+		
+	/* If device is SATA, add device to the disk array. */
+	disk[disk_count].sess = ahci_get_sess(funh, &disk[disk_count].dev_name);
+	if(disk[disk_count].sess != NULL) {
+		
+		ahci_get_sata_device_name(disk[disk_count].sess,
+		    SATA_DEV_NAME_LENGTH, disk[disk_count].sata_dev_name);
+		
+		ahci_get_block_size(disk[disk_count].sess,
+		    &disk[disk_count].block_size);
+		
+		ahci_get_num_blocks(disk[disk_count].sess, &disk[disk_count].blocks);
+				
+		printf("Device %s - %s , blocks: %lu, block_size: %lu\n", 
+		    disk[disk_count].dev_name, disk[disk_count].sata_dev_name,
+			    (long unsigned int) disk[disk_count].blocks,
+				(long unsigned int) disk[disk_count].block_size);
+
+		++disk_count;
+	}
+	
+	/* search children */
+	rc = devman_fun_get_child(funh, &devh);
+	if (rc == ENOENT)
+		return EOK;
+
+	if (rc != EOK) {
+		printf(NAME ": Failed getting child device for function %s.\n", "xxx");
+		return rc;
+	}
+
+	rc = devman_dev_get_functions(devh, &cfuns, &count);
+	if (rc != EOK) {
+		printf(NAME ": Failed getting list of functions for device %s.\n",
+		    "xxx");
+		return rc;
+	}
+
+	for (i = 0; i < count; i++)
+		scan_device_tree(cfuns[i]);
+
+	free(cfuns);
+	return EOK;
+}
+
+/** Find sata devices in device tree from root.
+ *
+ *  @return EOK if succeed, error code otherwise.
+ *
+ */
+static int get_sata_disks()
+{
+	devman_handle_t root_fun;
+	int rc;
+	
+	disk_count = 0;
+
+	rc = devman_fun_get_handle("/", &root_fun, 0);
+	if (rc != EOK) {
+		printf(NAME ": Error resolving root function.\n");
+		return EIO;
+	}
+	
+	scan_device_tree(root_fun);
+	
+	return EOK;
+}
+
+/** Block device connection handler. */
+static void sata_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	void *fs_va = NULL;
+	ipc_callid_t callid;
+	ipc_call_t call;
+	sysarg_t method;
+	service_id_t dsid;
+	/* Size of the communication area. */
+	size_t comm_size;	
+	unsigned int flags;
+	int retval = 0;
+	uint64_t ba;
+	size_t cnt;
+	int disk_id, i;
+
+	/* Get the device service ID. */
+	dsid = IPC_GET_ARG1(*icall);
+
+	/* Determine which disk device is the client connecting to. */
+	disk_id = -1;
+	for (i = 0; i < MAXDISKS; i++)
+		if (disk[i].service_id == dsid)
+			disk_id = i;
+
+	if (disk_id < 0) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	/* Answer the IPC_M_CONNECT_ME_TO call. */
+	async_answer_0(iid, EOK);
+
+	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
+		async_answer_0(callid, EHANGUP);
+		return;
+	}
+
+	(void) async_share_out_finalize(callid, &fs_va);
+	if (fs_va == (void *) -1) {
+		async_answer_0(callid, EHANGUP);
+		return;
+	}
+
+	while (true) {
+		callid = async_get_call(&call);
+		method = IPC_GET_IMETHOD(call);
+		
+		if (!method) {
+			/* The other side has hung up. */
+			async_answer_0(callid, EOK);
+			return;
+		}
+		
+		switch (method) {
+			case BD_READ_BLOCKS:
+				ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
+				cnt = IPC_GET_ARG3(call);
+				if (cnt * disk[disk_id].block_size > comm_size) {
+					retval = ELIMIT;
+					break;
+				}
+				retval = ahci_read_blocks(disk[disk_id].sess, ba, cnt, fs_va);
+				break;
+			case BD_WRITE_BLOCKS:
+				ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
+				cnt = IPC_GET_ARG3(call);
+				if (cnt * disk[disk_id].block_size > comm_size) {
+					retval = ELIMIT;
+					break;
+				}
+				retval = ahci_write_blocks(disk[disk_id].sess, ba, cnt, fs_va);
+				break;
+			case BD_GET_BLOCK_SIZE:
+				async_answer_1(callid, EOK, disk[disk_id].block_size);
+				continue;
+			case BD_GET_NUM_BLOCKS:
+				async_answer_2(callid, EOK, LOWER32(disk[disk_id].blocks),
+				    UPPER32(disk[disk_id].blocks));
+				break;
+			default:
+				retval = EINVAL;
+				break;
+			}
+		async_answer_0(callid, retval);
+	}
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	
+	async_set_client_connection(sata_bd_connection);
+	rc = loc_server_register(NAME);
+	if (rc < 0) {
+		printf(NAME ": Unable to register driver.\n");
+		return rc;
+	}
+	
+	rc = get_sata_disks();
+	if (rc != EOK) {
+		return rc;
+	}
+
+	for(int i=0; i < disk_count; i++) {
+		char name[1024];
+		snprintf(name, 1024, "%s/%s", NAMESPACE, disk[i].dev_name);
+		rc = loc_service_register(name, &disk[i].service_id);
+		if (rc != EOK) {
+			printf(NAME ": Unable to register device %s.\n", name);
+			return rc;
+		}
+	}
+		
+	printf(NAME ": Accepting connections\n");
+	task_retval(0);
+	async_manager();
+
+	/* Not reached */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/bd/sata_bd/sata_bd.h
===================================================================
--- uspace/srv/bd/sata_bd/sata_bd.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/srv/bd/sata_bd/sata_bd.h	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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 bd
+ * @{
+ */
+/** @file SATA block device driver definitions.
+ */
+
+#ifndef __SATA_BD_H__
+#define __SATA_BD_H__
+
+#define SATA_DEV_NAME_LENGTH 256
+
+#include <sys/types.h>
+#include <loc.h>
+
+/** SATA Block Device. */
+typedef struct {
+	/** Device name in device tree. */ 
+	char* dev_name; 
+	/** SATA Device name. */ 
+	char sata_dev_name[SATA_DEV_NAME_LENGTH]; 
+	/** Session to device methods. */
+	async_sess_t* sess; 
+	/** Loc service id. */
+	service_id_t service_id;
+	/** Number of blocks. */
+	uint64_t blocks; 
+	/** Size of block. */
+	size_t block_size; 
+} sata_bd_dev_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/srv/devman/main.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -419,5 +419,7 @@
 	
 	/* Check that function with same name is not there already. */
-	if (find_fun_node_in_device(tree, pdev, fun_name) != NULL) {
+	fun_node_t *tfun = find_fun_node_in_device(tree, pdev, fun_name);
+	if (tfun) {
+		fun_del_ref(tfun);	/* drop the new unwanted reference */
 		fibril_rwlock_write_unlock(&tree->rwlock);
 		dev_del_ref(pdev);
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/srv/hid/console/console.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -76,7 +76,11 @@
 } console_state_t;
 
+#define UTF8_CHAR_BUFFER_SIZE (STR_BOUNDS(1) + 1)
+
 typedef struct {
 	atomic_t refcnt;           /**< Connection reference count */
 	prodcons_t input_pc;       /**< Incoming keyboard events */
+	char char_remains[UTF8_CHAR_BUFFER_SIZE]; /**< Not yet sent bytes of last char event. */
+	size_t char_remains_len;   /**< Number of not yet sent bytes. */
 	
 	fibril_mutex_t mtx;        /**< Lock protecting mutable fields */
@@ -613,14 +617,37 @@
 	
 	size_t pos = 0;
+	
+	/*
+	 * Read input from keyboard and copy it to the buffer.
+	 * We need to handle situation when wchar is split by 2 following
+	 * reads.
+	 */
 	while (pos < size) {
-		link_t *link = prodcons_consume(&cons->input_pc);
-		kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
-		
-		if (event->type == KEY_PRESS) {
-			buf[pos] = event->c;
+		/* Copy to the buffer remaining characters. */
+		while ((pos < size) && (cons->char_remains_len > 0)) {
+			buf[pos] = cons->char_remains[0];
 			pos++;
-		}
-		
-		free(event);
+			
+			/* Unshift the array. */
+			for (size_t i = 1; i < cons->char_remains_len; i++)
+				cons->char_remains[i - 1] = cons->char_remains[i];
+			
+			cons->char_remains_len--;
+		}
+		
+		/* Still not enough? Then get another key from the queue. */
+		if (pos < size) {
+			link_t *link = prodcons_consume(&cons->input_pc);
+			kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
+			
+			/* Accept key presses of printable chars only. */
+			if ((event->type == KEY_PRESS) && (event->c != 0)) {
+				wchar_t tmp[2] = { event->c, 0 };
+				wstr_to_str(cons->char_remains, UTF8_CHAR_BUFFER_SIZE, tmp);
+				cons->char_remains_len = str_size(cons->char_remains);
+			}
+			
+			free(event);
+		}
 	}
 	
@@ -930,4 +957,5 @@
 		fibril_mutex_initialize(&consoles[i].mtx);
 		prodcons_initialize(&consoles[i].input_pc);
+		consoles[i].char_remains_len = 0;
 		
 		if (graphics_state == GRAPHICS_FULL) {
Index: uspace/srv/hid/input/port/ns16550.c
===================================================================
--- uspace/srv/hid/input/port/ns16550.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/srv/hid/input/port/ns16550.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -84,5 +84,5 @@
 	},
 	{
-		.cmd = CMD_BTEST,
+		.cmd = CMD_AND,
 		.value = LSR_DATA_READY,
 		.srcarg = 1,
Index: uspace/srv/hid/input/port/pl050.c
===================================================================
--- uspace/srv/hid/input/port/pl050.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/srv/hid/input/port/pl050.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -80,5 +80,5 @@
 	},
 	{
-		.cmd = CMD_BTEST,
+		.cmd = CMD_AND,
 		.value = PL050_STAT_RXFULL,
 		.srcarg = 1,
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.c
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -116,9 +116,9 @@
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,	/* will be patched in run-time */
+		.addr = NULL,
 		.dstarg = 1
 	},
 	{
-		.cmd = CMD_BTEST,
+		.cmd = CMD_AND,
 		.value = SR_INT,
 		.srcarg = 1,
Index: uspace/srv/loader/Makefile
===================================================================
--- uspace/srv/loader/Makefile	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/srv/loader/Makefile	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -44,5 +44,5 @@
 GENERIC_SOURCES = \
 	main.c \
-	interp.s
+	interp.S
 
 SOURCES = \
Index: uspace/srv/loader/interp.S
===================================================================
--- uspace/srv/loader/interp.S	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
+++ uspace/srv/loader/interp.S	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -0,0 +1,21 @@
+#
+# Provide a string to be included in a special DT_INTERP header, even though
+# this is a statically-linked executable. This will mark the binary as
+# the program loader.
+#
+
+#if ((defined(UARCH_abs32le)) && (defined(COMPILER_gcc_cross)) \
+    && (defined(CROSS_TARGET_arm32)))
+	#define ATSIGN(arg)  % ## arg
+#endif
+
+#ifdef UARCH_arm32
+	#define ATSIGN(arg)  % ## arg
+#endif
+
+#ifndef ATSIGN
+	#define ATSIGN(arg)  @ ## arg
+#endif
+
+.section .interp, "a", ATSIGN(progbits)
+	.string "kernel"
Index: uspace/srv/loader/interp.s
===================================================================
--- uspace/srv/loader/interp.s	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ 	(revision )
@@ -1,7 +1,0 @@
-#
-# Provide a string to be included in a special DT_INTERP header, even though
-# this is a statically-linked executable. This will mark the binary as
-# the program loader.
-#
-.section .interp , ""
-	.string "kernel"
Index: uspace/srv/net/tcp/sock.c
===================================================================
--- uspace/srv/net/tcp/sock.c	(revision bc216a07a86e40d74455b7f4d6fb8f65e195443d)
+++ uspace/srv/net/tcp/sock.c	(revision da68871a1ca8b07736e941032a954a3f19eadccc)
@@ -779,4 +779,9 @@
 	}
 
+	/* Grab recv_buffer_lock because of CV wait in tcp_sock_recv_fibril() */
+	fibril_mutex_lock(&socket->recv_buffer_lock);
+	socket->sock_core = NULL;
+	fibril_mutex_unlock(&socket->recv_buffer_lock);
+
 	rc = socket_destroy(NULL, socket_id, &client->sockets, &gsock,
 	    tcp_free_sock_data);
@@ -839,8 +844,9 @@
 	log_msg(LVL_DEBUG, "tcp_sock_recv_fibril()");
 
+	fibril_mutex_lock(&sock->recv_buffer_lock);
+
 	while (true) {
 		log_msg(LVL_DEBUG, "call tcp_uc_receive()");
-		fibril_mutex_lock(&sock->recv_buffer_lock);
-		while (sock->recv_buffer_used != 0)
+		while (sock->recv_buffer_used != 0 && sock->sock_core != NULL)
 			fibril_condvar_wait(&sock->recv_buffer_cv,
 			    &sock->recv_buffer_lock);
@@ -852,6 +858,6 @@
 			sock->recv_error = trc;
 			fibril_condvar_broadcast(&sock->recv_buffer_cv);
-			fibril_mutex_unlock(&sock->recv_buffer_lock);
-			tcp_sock_notify_data(sock->sock_core);
+			if (sock->sock_core != NULL)
+				tcp_sock_notify_data(sock->sock_core);
 			break;
 		}
@@ -861,7 +867,9 @@
 		sock->recv_buffer_used = data_len;
 		fibril_condvar_broadcast(&sock->recv_buffer_cv);
-		fibril_mutex_unlock(&sock->recv_buffer_lock);
-		tcp_sock_notify_data(sock->sock_core);
-	}
+		if (sock->sock_core != NULL)
+			tcp_sock_notify_data(sock->sock_core);
+	}
+
+	fibril_mutex_unlock(&sock->recv_buffer_lock);
 
 	tcp_uc_delete(sock->conn);
