Index: uspace/drv/audio/hdaudio/hdaudio.c
===================================================================
--- uspace/drv/audio/hdaudio/hdaudio.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/audio/hdaudio/hdaudio.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -36,6 +36,6 @@
 #include <bitops.h>
 #include <ddi.h>
+#include <device/hw_res.h>
 #include <device/hw_res_parsed.h>
-#include <irc.h>
 #include <stdio.h>
 #include <errno.h>
@@ -175,5 +175,5 @@
 
 	ddf_msg(LVL_NOTE, "create parent sess");
-	hda->parent_sess = ddf_dev_parent_sess_create(dev);
+	hda->parent_sess = ddf_dev_parent_sess_get(dev);
 	if (hda->parent_sess == NULL) {
 		ddf_msg(LVL_ERROR, "Failed connecting parent driver.\n");
@@ -257,5 +257,5 @@
 	ddf_msg(LVL_NOTE, "range0.base=%zu", hdaudio_irq_pio_ranges[0].base);
 
-	rc = irc_enable_interrupt(res.irqs.irqs[0]);
+	rc = hw_res_enable_interrupt(hda->parent_sess, res.irqs.irqs[0]);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed enabling interrupt. (%d)", rc);
@@ -263,7 +263,8 @@
 	}
 
-	rc = register_interrupt_handler(dev, res.irqs.irqs[0],
+	int irq_cap = register_interrupt_handler(dev, res.irqs.irqs[0],
 	    hdaudio_interrupt, &irq_code);
-	if (rc != EOK) {
+	if (irq_cap < 0) {
+		rc = irq_cap;
 		ddf_msg(LVL_ERROR, "Failed registering interrupt handler. (%d)",
 		    rc);
Index: uspace/drv/audio/sb16/dsp.c
===================================================================
--- uspace/drv/audio/sb16/dsp.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/audio/sb16/dsp.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -35,6 +35,6 @@
 #include <as.h>
 #include <stdbool.h>
+#include <ddf/driver.h>
 #include <ddi.h>
-#include <devman.h>
 #include <device/hw_res.h>
 #include <libarch/ddi.h>
@@ -75,5 +75,5 @@
 		[DSP_NO_BUFFER] = "NO BUFFER",
 	};
-	if (state < ARRAY_SIZE(state_names))
+	if ((size_t)state < ARRAY_SIZE(state_names))
 		return state_names[state];
 	return "UNKNOWN";
@@ -144,7 +144,9 @@
 {
 	dsp_write(dsp, SET_SAMPLING_RATE_OUTPUT);
-	dsp_write(dsp, rate >> 8);
-	dsp_write(dsp, rate & 0xff);
-	ddf_log_verbose("Sampling rate: %hhx:%hhx.", rate >> 8, rate & 0xff);
+	uint8_t rate_lo = rate & 0xff;
+	uint8_t rate_hi = rate >> 8;
+	dsp_write(dsp, rate_hi);
+	dsp_write(dsp, rate_lo);
+	ddf_log_verbose("Sampling rate: %hhx:%hhx.", rate_hi, rate_lo);
 }
 
@@ -159,13 +161,9 @@
 static inline int setup_dma(sb_dsp_t *dsp, uintptr_t pa, size_t size)
 {
-	async_sess_t *sess = devman_parent_device_connect(
-	    ddf_dev_get_handle(dsp->sb_dev), IPC_FLAG_BLOCKING);
-
-	const int ret = hw_res_dma_channel_setup(sess,
+	async_sess_t *sess = ddf_dev_parent_sess_get(dsp->sb_dev);
+
+	return hw_res_dma_channel_setup(sess,
 	    dsp->dma16_channel, pa, size,
 	    DMA_MODE_READ | DMA_MODE_AUTO | DMA_MODE_ON_DEMAND);
-
-	async_hangup(sess);
-	return ret;
 }
 
@@ -202,9 +200,4 @@
 	
 	return ret;
-}
-
-static inline size_t sample_count(pcm_sample_format_t format, size_t byte_count)
-{
-	return byte_count / pcm_sample_format_size(format);
 }
 
@@ -307,10 +300,8 @@
 
 	assert(dsp->buffer.data);
-	async_sess_t *sess = devman_parent_device_connect(
-	    ddf_dev_get_handle(dsp->sb_dev), IPC_FLAG_BLOCKING);
+	async_sess_t *sess = ddf_dev_parent_sess_get(dsp->sb_dev);
 
 	// TODO: Assumes DMA 16
 	const int remain = hw_res_dma_channel_remain(sess, dsp->dma16_channel);
-	async_hangup(sess);
 	if (remain >= 0) {
 		*pos = dsp->buffer.size - remain;
Index: uspace/drv/audio/sb16/main.c
===================================================================
--- uspace/drv/audio/sb16/main.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/audio/sb16/main.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -37,5 +37,4 @@
 #include <ddf/log.h>
 #include <device/hw_res_parsed.h>
-#include <devman.h>
 #include <assert.h>
 #include <stdio.h>
@@ -51,5 +50,5 @@
 static int sb_get_res(ddf_dev_t *device, addr_range_t **pp_sb_regs,
     addr_range_t **pp_mpu_regs, int *irq, int *dma8, int *dma16);
-static int sb_enable_interrupts(ddf_dev_t *device);
+static int sb_enable_interrupt(ddf_dev_t *device, int irq);
 
 static driver_ops_t sb_driver_ops = {
@@ -94,4 +93,5 @@
 	irq_cmd_t irq_cmds[irq_cmd_count];
 	irq_pio_range_t irq_ranges[1];
+	int irq_cap;
 
 	sb16_t *soft_state = ddf_dev_data_alloc(device, sizeof(sb16_t));
@@ -123,6 +123,8 @@
 	};
 
-	rc = register_interrupt_handler(device, irq, irq_handler, &irq_code);
-	if (rc != EOK) {
+	irq_cap = register_interrupt_handler(device, irq, irq_handler,
+	    &irq_code);
+	if (irq_cap < 0) {
+		rc = irq_cap;
 		ddf_log_error("Failed to register irq handler: %s.",
 		    str_error(rc));
@@ -132,5 +134,5 @@
 	handler_regd = true;
 
-	rc = sb_enable_interrupts(device);
+	rc = sb_enable_interrupt(device, irq);
 	if (rc != EOK) {
 		ddf_log_error("Failed to enable interrupts: %s.",
@@ -168,5 +170,5 @@
 error:
 	if (handler_regd)
-		unregister_interrupt_handler(device, irq);
+		unregister_interrupt_handler(device, irq_cap);
 	return rc;
 }
@@ -177,7 +179,6 @@
 	assert(device);
 
-	async_sess_t *parent_sess = devman_parent_device_connect(
-	    ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
-	if (!parent_sess)
+	async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
+	if (parent_sess == NULL)
 		return ENOMEM;
 
@@ -185,5 +186,4 @@
 	hw_res_list_parsed_init(&hw_res);
 	const int ret = hw_res_get_list_parsed(parent_sess, &hw_res, 0);
-	async_hangup(parent_sess);
 	if (ret != EOK) {
 		return ret;
@@ -242,15 +242,11 @@
 }
 
-int sb_enable_interrupts(ddf_dev_t *device)
-{
-	async_sess_t *parent_sess = devman_parent_device_connect(
-	    ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
-	if (!parent_sess)
+static int sb_enable_interrupt(ddf_dev_t *device, int irq)
+{
+	async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
+	if (parent_sess == NULL)
 		return ENOMEM;
 
-	bool enabled = hw_res_enable_interrupt(parent_sess);
-	async_hangup(parent_sess);
-
-	return enabled ? EOK : EIO;
+	return hw_res_enable_interrupt(parent_sess, irq);
 }
 
Index: uspace/drv/block/ahci/ahci.c
===================================================================
--- uspace/drv/block/ahci/ahci.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/block/ahci/ahci.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -36,7 +36,7 @@
 #include <ddf/interrupt.h>
 #include <ddf/log.h>
+#include <device/hw_res.h>
 #include <device/hw_res_parsed.h>
 #include <pci_dev_iface.h>
-#include <irc.h>
 #include <ahci_iface.h>
 #include "ahci.h"
@@ -1140,5 +1140,5 @@
 	
 	/* Connect to parent device */
-	ahci->parent_sess = ddf_dev_parent_sess_create(dev);
+	ahci->parent_sess = ddf_dev_parent_sess_get(dev);
 	if (ahci->parent_sess == NULL)
 		return NULL;
@@ -1185,12 +1185,13 @@
 	ct.ranges = ahci_ranges;
 	
-	int rc = register_interrupt_handler(dev, hw_res_parsed.irqs.irqs[0],
-	    ahci_interrupt, &ct);
-	if (rc != EOK) {
+	int irq_cap = register_interrupt_handler(dev,
+	    hw_res_parsed.irqs.irqs[0], ahci_interrupt, &ct);
+	if (irq_cap < 0) {
 		ddf_msg(LVL_ERROR, "Failed registering interrupt handler.");
 		goto error_register_interrupt_handler;
 	}
 	
-	rc = irc_enable_interrupt(hw_res_parsed.irqs.irqs[0]);
+	int rc = hw_res_enable_interrupt(ahci->parent_sess,
+	    hw_res_parsed.irqs.irqs[0]);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed enable interupt.");
@@ -1202,5 +1203,5 @@
 	
 error_enable_interrupt:
-	unregister_interrupt_handler(dev, hw_res_parsed.irqs.irqs[0]);
+	unregister_interrupt_handler(dev, irq_cap);
 	
 error_register_interrupt_handler:
Index: uspace/drv/block/ahci/ahci.h
===================================================================
--- uspace/drv/block/ahci/ahci.h	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/block/ahci/ahci.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -35,5 +35,4 @@
 
 #include <async.h>
-#include <devman.h>
 #include <ddf/interrupt.h>
 #include <stdio.h>
@@ -92,7 +91,4 @@
 	ahci_port_is_t event_pxis;
 	
-	/** Block device service id. */
-	service_id_t service_id;
-	
 	/** Number of device data blocks. */
 	uint64_t blocks;
Index: uspace/drv/block/ata_bd/main.c
===================================================================
--- uspace/drv/block/ata_bd/main.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/block/ata_bd/main.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -68,5 +68,5 @@
 	int rc;
 
-	parent_sess = ddf_dev_parent_sess_create(dev);
+	parent_sess = ddf_dev_parent_sess_get(dev);
 	if (parent_sess == NULL)
 		return ENOMEM;
Index: uspace/drv/block/ddisk/ddisk.c
===================================================================
--- uspace/drv/block/ddisk/ddisk.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/block/ddisk/ddisk.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -112,4 +112,6 @@
 	ddisk_regs_t *ddisk_regs;
 
+	int irq_cap;
+
 	bd_srvs_t bds;
 } ddisk_t;
@@ -286,5 +288,5 @@
 	int rc;
 
-	parent_sess = ddf_dev_parent_sess_create(dev);
+	parent_sess = ddf_dev_parent_sess_get(dev);
 	if (parent_sess == NULL)
 		return ENOMEM;
@@ -447,4 +449,6 @@
 	ddisk->bds.sarg = ddisk;
 
+	ddisk->irq_cap = -1;
+
 	/*
 	 * Enable access to ddisk's PIO registers.
@@ -499,7 +503,8 @@
 	ddisk_irq_commands[0].addr = (void *) &res_phys->status;
 	ddisk_irq_commands[3].addr = (void *) &res_phys->command;
-	rc = register_interrupt_handler(dev, ddisk->ddisk_res.irq,
+	ddisk->irq_cap = register_interrupt_handler(dev, ddisk->ddisk_res.irq,
 	    ddisk_irq_handler, &ddisk_irq_code);
-	if (rc != EOK) {
+	if (ddisk->irq_cap < 0) {
+		rc = ddisk->irq_cap;
 		ddf_msg(LVL_ERROR, "Failed to register interrupt handler.");
 		goto error;
@@ -541,5 +546,5 @@
 	}
 
-	unregister_interrupt_handler(ddisk->dev, ddisk->ddisk_res.irq);
+	unregister_interrupt_handler(ddisk->dev, ddisk->irq_cap);
 	
 	rc = pio_disable(ddisk->ddisk_regs, sizeof(ddisk_regs_t));
Index: uspace/drv/bus/adb/cuda_adb/Makefile
===================================================================
--- uspace/drv/bus/adb/cuda_adb/Makefile	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/bus/adb/cuda_adb/Makefile	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2010 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = cuda_adb
+
+SOURCES = \
+	cuda_adb.c \
+	main.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/adb/cuda_adb/cuda_adb.c
===================================================================
--- uspace/drv/bus/adb/cuda_adb/cuda_adb.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/bus/adb/cuda_adb/cuda_adb.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/** @file VIA-CUDA Apple Desktop Bus driver
+ *
+ * Note: We should really do a full bus scan at the beginning and resolve
+ * address conflicts. Also we should consider the handler ID in r3. Instead
+ * we just assume a keyboard at address 2 or 8 and a mouse at address 9.
+ */
+
+#include <assert.h>
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <ddi.h>
+#include <errno.h>
+#include <ipc/adb.h>
+#include <libarch/ddi.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <sysinfo.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cuda_adb.h"
+#include "cuda_hw.h"
+
+#define NAME  "cuda_adb"
+
+static void cuda_dev_connection(ipc_callid_t, ipc_call_t *, void *);
+static int cuda_init(cuda_t *);
+static void cuda_irq_handler(ipc_callid_t, ipc_call_t *, void *);
+
+static void cuda_irq_listen(cuda_t *);
+static void cuda_irq_receive(cuda_t *);
+static void cuda_irq_rcv_end(cuda_t *, void *, size_t *);
+static void cuda_irq_send_start(cuda_t *);
+static void cuda_irq_send(cuda_t *);
+
+static void cuda_packet_handle(cuda_t *, uint8_t *, size_t);
+static void cuda_send_start(cuda_t *);
+static void cuda_autopoll_set(cuda_t *, bool);
+
+static void adb_packet_handle(cuda_t *, uint8_t *, size_t, bool);
+
+static irq_pio_range_t cuda_ranges[] = {
+	{
+		.base = 0,
+		.size = sizeof(cuda_regs_t)
+	}
+};
+
+static irq_cmd_t cuda_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = NULL,
+		.dstarg = 1
+	},
+	{
+		.cmd = CMD_AND,
+		.value = SR_INT,
+		.srcarg = 1,
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 1,
+		.srcarg = 2
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+
+static irq_code_t cuda_irq_code = {
+	sizeof(cuda_ranges) / sizeof(irq_pio_range_t),
+	cuda_ranges,
+	sizeof(cuda_cmds) / sizeof(irq_cmd_t),
+	cuda_cmds
+};
+
+static int cuda_dev_create(cuda_t *cuda, const char *name, adb_dev_t **rdev)
+{
+	adb_dev_t *dev = NULL;
+	ddf_fun_t *fun;
+	int rc;
+
+	fun = ddf_fun_create(cuda->dev, fun_exposed, name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function '%s'.", name);
+		rc = ENOMEM;
+		goto error;
+	}
+
+	dev = ddf_fun_data_alloc(fun, sizeof(adb_dev_t));
+	if (dev == NULL) {
+		ddf_msg(LVL_ERROR, "Failed allocating memory for '%s'.", name);
+		rc = ENOMEM;
+		goto error;
+	}
+
+	dev->fun = fun;
+	list_append(&dev->lcuda, &cuda->devs);
+
+	ddf_fun_set_conn_handler(fun, cuda_dev_connection);
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function '%s'.", name);
+		goto error;
+	}
+
+	*rdev = dev;
+	return EOK;
+error:
+	if (fun != NULL)
+		ddf_fun_destroy(fun);
+	return rc;
+}
+
+int cuda_add(cuda_t *cuda, cuda_res_t *res)
+{
+	adb_dev_t *kbd = NULL;
+	adb_dev_t *mouse = NULL;
+	int rc;
+
+	cuda->phys_base = res->base;
+
+	rc = cuda_dev_create(cuda, "kbd", &kbd);
+	if (rc != EOK)
+		goto error;
+
+	rc = cuda_dev_create(cuda, "mouse", &mouse);
+	if (rc != EOK)
+		goto error;
+
+	cuda->addr_dev[2] = kbd;
+	cuda->addr_dev[8] = kbd;
+
+	cuda->addr_dev[9] = mouse;
+
+	rc = cuda_init(cuda);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed initializing CUDA hardware.");
+		return rc;
+	}
+
+	return EOK;
+error:
+	return rc;
+}
+
+int cuda_remove(cuda_t *cuda)
+{
+	return ENOTSUP;
+}
+
+int cuda_gone(cuda_t *cuda)
+{
+	return ENOTSUP;
+}
+
+/** Device connection handler */
+static void cuda_dev_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	adb_dev_t *dev = (adb_dev_t *) ddf_fun_data_get((ddf_fun_t *) arg);
+	ipc_callid_t callid;
+	ipc_call_t call;
+	sysarg_t method;
+
+	/* Answer the IPC_M_CONNECT_ME_TO call. */
+	async_answer_0(iid, EOK);
+
+	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;
+		}
+
+		async_sess_t *sess =
+		    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
+		if (sess != NULL) {
+			dev->client_sess = sess;
+			async_answer_0(callid, EOK);
+		} else {
+			async_answer_0(callid, EINVAL);
+		}
+	}
+}
+
+static int cuda_init(cuda_t *cuda)
+{
+	int rc;
+
+	void *vaddr;
+	rc = pio_enable((void *) cuda->phys_base, sizeof(cuda_regs_t),
+	    &vaddr);
+	if (rc != EOK)
+		return rc;
+
+	cuda->regs = vaddr;
+	cuda->xstate = cx_listen;
+	cuda->bidx = 0;
+	cuda->snd_bytes = 0;
+
+	fibril_mutex_initialize(&cuda->dev_lock);
+
+	/* Disable all interrupts from CUDA. */
+	pio_write_8(&cuda->regs->ier, IER_CLR | ALL_INT);
+
+	cuda_irq_code.ranges[0].base = (uintptr_t) cuda->phys_base;
+	cuda_irq_code.cmds[0].addr = (void *) &((cuda_regs_t *)
+	    cuda->phys_base)->ifr;
+	async_irq_subscribe(10, cuda_irq_handler, cuda, &cuda_irq_code);
+
+	/* Enable SR interrupt. */
+	pio_write_8(&cuda->regs->ier, TIP | TREQ);
+	pio_write_8(&cuda->regs->ier, IER_SET | SR_INT);
+
+	/* Enable ADB autopolling. */
+	cuda_autopoll_set(cuda, true);
+
+	return EOK;
+}
+
+static void cuda_irq_handler(ipc_callid_t iid, ipc_call_t *call, void *arg)
+{
+	uint8_t rbuf[CUDA_RCV_BUF_SIZE];
+	cuda_t *cuda = (cuda_t *)arg;
+	size_t len;
+	bool handle;
+
+	handle = false;
+	len = 0;
+
+	fibril_mutex_lock(&cuda->dev_lock);
+
+	switch (cuda->xstate) {
+	case cx_listen:
+		cuda_irq_listen(cuda);
+		break;
+	case cx_receive:
+		cuda_irq_receive(cuda);
+		break;
+	case cx_rcv_end:
+		cuda_irq_rcv_end(cuda, rbuf, &len);
+		handle = true;
+		break;
+	case cx_send_start:
+		cuda_irq_send_start(cuda);
+		break;
+	case cx_send:
+		cuda_irq_send(cuda);
+		break;
+	}
+
+	/* Lower IFR.SR_INT so that CUDA can generate next int by raising it. */
+	pio_write_8(&cuda->regs->ifr, SR_INT);
+
+	fibril_mutex_unlock(&cuda->dev_lock);
+
+	/* Handle an incoming packet. */
+	if (handle)
+		cuda_packet_handle(cuda, rbuf, len);
+}
+
+/** Interrupt in listen state.
+ *
+ * Start packet reception.
+ *
+ * @param cuda CUDA instance
+ */
+static void cuda_irq_listen(cuda_t *cuda)
+{
+	uint8_t b = pio_read_8(&cuda->regs->b);
+
+	if ((b & TREQ) != 0) {
+		ddf_msg(LVL_WARN, "cuda_irq_listen: no TREQ?!");
+		return;
+	}
+
+	pio_write_8(&cuda->regs->b, b & ~TIP);
+	cuda->xstate = cx_receive;
+}
+
+/** Interrupt in receive state.
+ *
+ * Receive next byte of packet.
+ *
+ * @param cuda CUDA instance
+ */
+static void cuda_irq_receive(cuda_t *cuda)
+{
+	uint8_t data = pio_read_8(&cuda->regs->sr);
+	if (cuda->bidx < CUDA_RCV_BUF_SIZE)
+		cuda->rcv_buf[cuda->bidx++] = data;
+
+	uint8_t b = pio_read_8(&cuda->regs->b);
+
+	if ((b & TREQ) == 0) {
+		pio_write_8(&cuda->regs->b, b ^ TACK);
+	} else {
+		pio_write_8(&cuda->regs->b, b | TACK | TIP);
+		cuda->xstate = cx_rcv_end;
+	}
+}
+
+/** Interrupt in rcv_end state.
+ *
+ * Terminate packet reception. Either go back to listen state or start
+ * receiving another packet if CUDA has one for us.
+ *
+ * @param cuda CUDA instance
+ * @param buf Buffer for storing received packet
+ * @param len Place to store length of received packet
+ */
+static void cuda_irq_rcv_end(cuda_t *cuda, void *buf, size_t *len)
+{
+	uint8_t b = pio_read_8(&cuda->regs->b);
+
+	if ((b & TREQ) == 0) {
+		cuda->xstate = cx_receive;
+		pio_write_8(&cuda->regs->b, b & ~TIP);
+	} else {
+		cuda->xstate = cx_listen;
+		cuda_send_start(cuda);
+	}
+
+	memcpy(buf, cuda->rcv_buf, cuda->bidx);
+	*len = cuda->bidx;
+	cuda->bidx = 0;
+}
+
+/** Interrupt in send_start state.
+ *
+ * Process result of sending first byte (and send second on success).
+ *
+ * @param cuda CUDA instance
+ */
+static void cuda_irq_send_start(cuda_t *cuda)
+{
+	uint8_t b;
+
+	b = pio_read_8(&cuda->regs->b);
+
+	if ((b & TREQ) == 0) {
+		/* Collision */
+		pio_write_8(&cuda->regs->acr, pio_read_8(&cuda->regs->acr) &
+		    ~SR_OUT);
+		pio_read_8(&cuda->regs->sr);
+		pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) |
+		    TIP | TACK);
+		cuda->xstate = cx_listen;
+		return;
+	}
+
+	pio_write_8(&cuda->regs->sr, cuda->snd_buf[1]);
+	pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) ^ TACK);
+	cuda->bidx = 2;
+
+	cuda->xstate = cx_send;
+}
+
+/** Interrupt in send state.
+ *
+ * Send next byte or terminate transmission.
+ *
+ * @param cuda CUDA instance
+ */
+static void cuda_irq_send(cuda_t *cuda)
+{
+	if (cuda->bidx < cuda->snd_bytes) {
+		/* Send next byte. */
+		pio_write_8(&cuda->regs->sr,
+		    cuda->snd_buf[cuda->bidx++]);
+		pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) ^ TACK);
+		return;
+	}
+
+	/* End transfer. */
+	cuda->snd_bytes = 0;
+	cuda->bidx = 0;
+
+	pio_write_8(&cuda->regs->acr, pio_read_8(&cuda->regs->acr) & ~SR_OUT);
+	pio_read_8(&cuda->regs->sr);
+	pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) | TACK | TIP);
+
+	cuda->xstate = cx_listen;
+	/* TODO: Match reply with request. */
+}
+
+static void cuda_packet_handle(cuda_t *cuda, uint8_t *data, size_t len)
+{
+	if (data[0] != PT_ADB)
+		return;
+	if (len < 2)
+		return;
+
+	adb_packet_handle(cuda, data + 2, len - 2, (data[1] & 0x40) != 0);
+}
+
+static void adb_packet_handle(cuda_t *cuda, uint8_t *data, size_t size,
+    bool autopoll)
+{
+	uint8_t dev_addr;
+	uint8_t reg_no;
+	uint16_t reg_val;
+	adb_dev_t *dev;
+	unsigned i;
+
+	dev_addr = data[0] >> 4;
+	reg_no = data[0] & 0x03;
+
+	if (size != 3) {
+		ddf_msg(LVL_WARN, "Unrecognized packet, size=%zu", size);
+		for (i = 0; i < size; ++i) {
+			ddf_msg(LVL_WARN, "  0x%02x", data[i]);
+		}
+		return;
+	}
+
+	if (reg_no != 0) {
+		ddf_msg(LVL_WARN, "Unrecognized packet, size=%zu", size);
+		for (i = 0; i < size; ++i) {
+			ddf_msg(LVL_WARN, "  0x%02x", data[i]);
+		}
+		return;
+	}
+
+	reg_val = ((uint16_t) data[1] << 8) | (uint16_t) data[2];
+
+	ddf_msg(LVL_DEBUG, "Received ADB packet for device address %d",
+	    dev_addr);
+	dev = cuda->addr_dev[dev_addr];
+	if (dev == NULL)
+		return;
+
+	async_exch_t *exch = async_exchange_begin(dev->client_sess);
+	async_msg_1(exch, ADB_REG_NOTIF, reg_val);
+	async_exchange_end(exch);
+}
+
+static void cuda_autopoll_set(cuda_t *cuda, bool enable)
+{
+	cuda->snd_buf[0] = PT_CUDA;
+	cuda->snd_buf[1] = CPT_AUTOPOLL;
+	cuda->snd_buf[2] = enable ? 0x01 : 0x00;
+	cuda->snd_bytes = 3;
+	cuda->bidx = 0;
+
+	cuda_send_start(cuda);
+}
+
+static void cuda_send_start(cuda_t *cuda)
+{
+	assert(cuda->xstate == cx_listen);
+
+	if (cuda->snd_bytes == 0)
+		return;
+
+	/* Check for incoming data. */
+	if ((pio_read_8(&cuda->regs->b) & TREQ) == 0)
+		return;
+
+	pio_write_8(&cuda->regs->acr, pio_read_8(&cuda->regs->acr) | SR_OUT);
+	pio_write_8(&cuda->regs->sr, cuda->snd_buf[0]);
+	pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) & ~TIP);
+
+	cuda->xstate = cx_send_start;
+}
+
+/** @}
+ */
Index: uspace/drv/bus/adb/cuda_adb/cuda_adb.h
===================================================================
--- uspace/drv/bus/adb/cuda_adb/cuda_adb.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/bus/adb/cuda_adb/cuda_adb.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2006 Martin Decky
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/** @file
+ */
+
+#ifndef CUDA_ADB_H_
+#define CUDA_ADB_H_
+
+#include <adt/list.h>
+#include <async.h>
+#include <ddf/driver.h>
+#include <fibril_synch.h>
+#include <loc.h>
+#include <stdint.h>
+#include "cuda_hw.h"
+
+enum {
+	CUDA_RCV_BUF_SIZE = 5
+};
+
+enum cuda_xfer_state {
+	cx_listen,
+	cx_receive,
+	cx_rcv_end,
+	cx_send_start,
+	cx_send
+};
+
+typedef struct {
+	uintptr_t base;
+	int irq;
+} cuda_res_t;
+
+/** ADB bus device */
+typedef struct {
+	ddf_fun_t *fun;
+	async_sess_t *client_sess;
+	link_t lcuda;
+	struct cuda *cuda;
+} adb_dev_t;
+
+/** CUDA ADB bus */
+typedef struct cude {
+	struct cuda_regs *regs;
+	uintptr_t phys_base;
+	ddf_dev_t *dev;
+
+	uint8_t rcv_buf[CUDA_RCV_BUF_SIZE];
+	uint8_t snd_buf[CUDA_RCV_BUF_SIZE];
+	size_t bidx;
+	size_t snd_bytes;
+	enum cuda_xfer_state xstate;
+	fibril_mutex_t dev_lock;
+
+	list_t devs;
+	adb_dev_t *addr_dev[ADB_MAX_ADDR];
+} cuda_t;
+
+extern int cuda_add(cuda_t *, cuda_res_t *);
+extern int cuda_remove(cuda_t *);
+extern int cuda_gone(cuda_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/drv/bus/adb/cuda_adb/cuda_adb.ma
===================================================================
--- uspace/drv/bus/adb/cuda_adb/cuda_adb.ma	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/bus/adb/cuda_adb/cuda_adb.ma	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -0,0 +1,1 @@
+10 cuda_adb
Index: uspace/drv/bus/adb/cuda_adb/cuda_hw.h
===================================================================
--- uspace/drv/bus/adb/cuda_adb/cuda_hw.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/bus/adb/cuda_adb/cuda_hw.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2006 Martin Decky
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/** @file
+ */
+
+#ifndef CUDA_HW_H_
+#define CUDA_HW_H_
+
+#include <stdint.h>
+
+typedef struct cuda_regs {
+	uint8_t b;
+	uint8_t pad0[0x1ff];
+
+	uint8_t a;
+	uint8_t pad1[0x1ff];
+
+	uint8_t dirb;
+	uint8_t pad2[0x1ff];
+
+	uint8_t dira;
+	uint8_t pad3[0x1ff];
+
+	uint8_t t1cl;
+	uint8_t pad4[0x1ff];
+
+	uint8_t t1ch;
+	uint8_t pad5[0x1ff];
+
+	uint8_t t1ll;
+	uint8_t pad6[0x1ff];
+
+	uint8_t t1lh;
+	uint8_t pad7[0x1ff];
+
+	uint8_t t2cl;
+	uint8_t pad8[0x1ff];
+
+	uint8_t t2ch;
+	uint8_t pad9[0x1ff];
+
+	uint8_t sr;
+	uint8_t pad10[0x1ff];
+
+	uint8_t acr;
+	uint8_t pad11[0x1ff];
+
+	uint8_t pcr;
+	uint8_t pad12[0x1ff];
+
+	uint8_t ifr;
+	uint8_t pad13[0x1ff];
+
+	uint8_t ier;
+	uint8_t pad14[0x1ff];
+
+	uint8_t anh;
+	uint8_t pad15[0x1ff];
+} cuda_regs_t;
+
+/** B register fields */
+enum {
+	TREQ	= 0x08,
+	TACK	= 0x10,
+	TIP	= 0x20
+};
+
+/** IER register fields */
+enum {
+	IER_CLR	= 0x00,
+	IER_SET	= 0x80,
+
+	SR_INT	= 0x04,
+	ALL_INT	= 0x7f
+};
+
+/** ACR register fields */
+enum {
+	SR_OUT	= 0x10
+};
+
+/** Packet types */
+enum {
+	PT_ADB	= 0x00,
+	PT_CUDA	= 0x01
+};
+
+/** CUDA packet types */
+enum {
+	CPT_AUTOPOLL	= 0x01
+};
+
+enum {
+	ADB_MAX_ADDR	= 16
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/drv/bus/adb/cuda_adb/main.c
===================================================================
--- uspace/drv/bus/adb/cuda_adb/main.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/bus/adb/cuda_adb/main.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2017 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/** @file VIA-CUDA Apple Desktop Bus driver
+ */
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <device/hw_res_parsed.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "cuda_adb.h"
+
+#define NAME  "cuda_adb"
+
+static int cuda_dev_add(ddf_dev_t *dev);
+static int cuda_dev_remove(ddf_dev_t *dev);
+static int cuda_dev_gone(ddf_dev_t *dev);
+static int cuda_fun_online(ddf_fun_t *fun);
+static int cuda_fun_offline(ddf_fun_t *fun);
+
+static driver_ops_t driver_ops = {
+	.dev_add = cuda_dev_add,
+	.dev_remove = cuda_dev_remove,
+	.dev_gone = cuda_dev_gone,
+	.fun_online = cuda_fun_online,
+	.fun_offline = cuda_fun_offline
+};
+
+static driver_t cuda_adb_driver = {
+	.name = NAME,
+	.driver_ops = &driver_ops
+};
+
+static int cuda_get_res(ddf_dev_t *dev, cuda_res_t *res)
+{
+	async_sess_t *parent_sess;
+	hw_res_list_parsed_t hw_res;
+	int rc;
+
+	parent_sess = ddf_dev_parent_sess_get(dev);
+	if (parent_sess == NULL)
+		return ENOMEM;
+
+	hw_res_list_parsed_init(&hw_res);
+	rc = hw_res_get_list_parsed(parent_sess, &hw_res, 0);
+	if (rc != EOK)
+		return rc;
+
+	if (hw_res.io_ranges.count != 1) {
+		rc = EINVAL;
+		goto error;
+	}
+
+	res->base = RNGABS(hw_res.io_ranges.ranges[0]);
+
+	if (hw_res.irqs.count != 1) {
+		rc = EINVAL;
+		goto error;
+	}
+
+	res->irq = hw_res.irqs.irqs[0];
+
+	return EOK;
+error:
+	hw_res_list_parsed_clean(&hw_res);
+	return rc;
+}
+
+static int cuda_dev_add(ddf_dev_t *dev)
+{
+	cuda_t *cuda;
+	cuda_res_t cuda_res;
+	int rc;
+
+        ddf_msg(LVL_DEBUG, "cuda_dev_add(%p)", dev);
+	cuda = ddf_dev_data_alloc(dev, sizeof(cuda_t));
+	if (cuda == NULL) {
+		ddf_msg(LVL_ERROR, "Failed allocating soft state.");
+		return ENOMEM;
+	}
+
+	cuda->dev = dev;
+	list_initialize(&cuda->devs);
+
+	rc = cuda_get_res(dev, &cuda_res);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed getting hardware resource list.\n");
+		return EIO;
+	}
+
+	return cuda_add(cuda, &cuda_res);
+}
+
+static int cuda_dev_remove(ddf_dev_t *dev)
+{
+        cuda_t *cuda = (cuda_t *)ddf_dev_data_get(dev);
+
+        ddf_msg(LVL_DEBUG, "cuda_dev_remove(%p)", dev);
+
+        return cuda_remove(cuda);
+}
+
+static int cuda_dev_gone(ddf_dev_t *dev)
+{
+        cuda_t *cuda = (cuda_t *)ddf_dev_data_get(dev);
+
+        ddf_msg(LVL_DEBUG, "cuda_dev_gone(%p)", dev);
+
+        return cuda_gone(cuda);
+}
+
+static int cuda_fun_online(ddf_fun_t *fun)
+{
+        ddf_msg(LVL_DEBUG, "cuda_fun_online()");
+        return ddf_fun_online(fun);
+}
+
+static int cuda_fun_offline(ddf_fun_t *fun)
+{
+        ddf_msg(LVL_DEBUG, "cuda_fun_offline()");
+        return ddf_fun_offline(fun);
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": VIA-CUDA Apple Desktop Bus driver\n");
+	ddf_log_init(NAME);
+	return ddf_driver_main(&cuda_adb_driver);
+}
+
+/** @}
+ */
Index: uspace/drv/bus/isa/i8237.c
===================================================================
--- uspace/drv/bus/isa/i8237.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/bus/isa/i8237.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -371,5 +371,5 @@
 	
 	/* 16 bit transfers are a bit special */
-	ddf_msg(LVL_DEBUG, "Unspoiled address %#" PRIx32 " (size %" PRIu16 ")",
+	ddf_msg(LVL_DEBUG, "Unspoiled address %#" PRIx32 " (size %" PRIu32 ")",
 	    pa, size);
 	if (is_dma16(channel)) {
@@ -388,5 +388,5 @@
 	
 	ddf_msg(LVL_DEBUG, "Setting channel %u to address %#" PRIx32 " "
-	    "(size %" PRIu16 "), mode %hhx.", channel, pa, size, mode);
+	    "(size %" PRIu32 "), mode %hhx.", channel, pa, size, mode);
 	
 	/* Mask DMA request */
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/bus/isa/isa.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -115,24 +115,47 @@
 }
 
-static bool isa_fun_enable_interrupt(ddf_fun_t *fnode)
-{
-	/* This is an old ugly way, copied from pci driver */
-	assert(fnode);
+static bool isa_fun_owns_interrupt(isa_fun_t *fun, int irq)
+{
+	const hw_resource_list_t *res = &fun->hw_resources;
+
+	/* Check that specified irq really belongs to the function */
+	for (size_t i = 0; i < res->count; ++i) {
+		if (res->resources[i].type == INTERRUPT &&
+		    res->resources[i].res.interrupt.irq == irq) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static int isa_fun_enable_interrupt(ddf_fun_t *fnode, int irq)
+{
 	isa_fun_t *fun = isa_fun(fnode);
-	assert(fun);
-
-	const hw_resource_list_t *res = &fun->hw_resources;
-	assert(res);
-	for (size_t i = 0; i < res->count; ++i) {
-		if (res->resources[i].type == INTERRUPT) {
-			int rc = irc_enable_interrupt(
-			    res->resources[i].res.interrupt.irq);
-
-			if (rc != EOK)
-				return false;
-		}
-	}
-
-	return true;
+
+	if (!isa_fun_owns_interrupt(fun, irq))
+		return EINVAL;
+
+	return irc_enable_interrupt(irq);
+}
+
+static int isa_fun_disable_interrupt(ddf_fun_t *fnode, int irq)
+{
+	isa_fun_t *fun = isa_fun(fnode);
+
+	if (!isa_fun_owns_interrupt(fun, irq))
+		return EINVAL;
+
+	return irc_disable_interrupt(irq);
+}
+
+static int isa_fun_clear_interrupt(ddf_fun_t *fnode, int irq)
+{
+	isa_fun_t *fun = isa_fun(fnode);
+
+	if (!isa_fun_owns_interrupt(fun, irq))
+		return EINVAL;
+
+	return irc_clear_interrupt(irq);
 }
 
@@ -185,4 +208,6 @@
 	.get_resource_list = isa_fun_get_resources,
 	.enable_interrupt = isa_fun_enable_interrupt,
+	.disable_interrupt = isa_fun_disable_interrupt,
+	.clear_interrupt = isa_fun_clear_interrupt,
 	.dma_channel_setup = isa_fun_setup_dma,
 	.dma_channel_remain = isa_fun_remain_dma,
@@ -643,5 +668,5 @@
 	list_initialize(&isa->functions);
 
-	sess = ddf_dev_parent_sess_create(dev);
+	sess = ddf_dev_parent_sess_get(dev);
 	if (sess == NULL) {
 		ddf_msg(LVL_ERROR, "isa_dev_add failed to connect to the "
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -99,23 +99,47 @@
 }
 
-static bool pciintel_enable_interrupt(ddf_fun_t *fnode)
-{
-	/* This is an old ugly way */
-	assert(fnode);
-	pci_fun_t *dev_data = pci_fun(fnode);
-	
-	size_t i = 0;
-	hw_resource_list_t *res = &dev_data->hw_resources;
-	for (; i < res->count; i++) {
-		if (res->resources[i].type == INTERRUPT) {
-			int rc = irc_enable_interrupt(
-			    res->resources[i].res.interrupt.irq);
-			
-			if (rc != EOK)
-				return false;
+static int pciintel_fun_owns_interrupt(pci_fun_t *fun, int irq)
+{
+	size_t i;
+	hw_resource_list_t *res = &fun->hw_resources;
+	
+	for (i = 0; i < res->count; i++) {
+		if (res->resources[i].type == INTERRUPT &&
+		    res->resources[i].res.interrupt.irq == irq) {
+			return true;
 		}
 	}
 	
-	return true;
+	return false;
+}
+
+static int pciintel_enable_interrupt(ddf_fun_t *fnode, int irq)
+{
+	pci_fun_t *fun = pci_fun(fnode);
+	
+	if (!pciintel_fun_owns_interrupt(fun, irq))
+		return EINVAL;
+
+	return irc_enable_interrupt(irq);
+}
+
+static int pciintel_disable_interrupt(ddf_fun_t *fnode, int irq)
+{
+	pci_fun_t *fun = pci_fun(fnode);
+	
+	if (!pciintel_fun_owns_interrupt(fun, irq))
+		return EINVAL;
+
+	return irc_disable_interrupt(irq);
+}
+
+static int pciintel_clear_interrupt(ddf_fun_t *fnode, int irq)
+{
+	pci_fun_t *fun = pci_fun(fnode);
+	
+	if (!pciintel_fun_owns_interrupt(fun, irq))
+		return EINVAL;
+
+	return irc_clear_interrupt(irq);
 }
 
@@ -187,4 +211,6 @@
 	.get_resource_list = &pciintel_get_resources,
 	.enable_interrupt = &pciintel_enable_interrupt,
+	.disable_interrupt = &pciintel_disable_interrupt,
+	.clear_interrupt = &pciintel_clear_interrupt,
 };
 
@@ -683,5 +709,5 @@
 	bus->dnode = dnode;
 	
-	sess = ddf_dev_parent_sess_create(dnode);
+	sess = ddf_dev_parent_sess_get(dnode);
 	if (sess == NULL) {
 		ddf_msg(LVL_ERROR, "pci_dev_add failed to connect to the "
Index: uspace/drv/bus/usb/ehci/res.c
===================================================================
--- uspace/drv/bus/usb/ehci/res.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/bus/usb/ehci/res.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -39,5 +39,5 @@
 #include <str_error.h>
 #include <assert.h>
-#include <devman.h>
+#include <ddf/driver.h>
 #include <ddi.h>
 #include <usb/debug.h>
@@ -176,7 +176,6 @@
 	assert(device);
 
-	async_sess_t *parent_sess = devman_parent_device_connect(
-	    ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
-	if (!parent_sess)
+	async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
+	if (parent_sess == NULL)
 		return ENOMEM;
 
Index: uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -78,5 +78,5 @@
 
 	/* Allow less data on input. */
-	if (dir == USB_DIRECTION_IN) {
+	if (direction == USB_DIRECTION_IN) {
 		OHCI_MEM32_SET(instance->status, TD_STATUS_ROUND_FLAG);
 	}
Index: uspace/drv/bus/usb/ohci/ohci_rh.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_rh.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/bus/usb/ohci/ohci_rh.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -361,5 +361,5 @@
 	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);
+		    "C_SUSPEND, C_OC or C_RESET on port %u.\n", port);
 		/* Bit offsets correspond to the feature number */
 		OHCI_WR(hub->registers->rh_port_status[port],
@@ -410,5 +410,5 @@
 	case USB_HUB_FEATURE_PORT_RESET:   /*4*/
 		usb_log_debug2("Setting port POWER, ENABLE, SUSPEND or RESET "
-		    "on port %"PRIu16".\n", port);
+		    "on port %u.\n", port);
 		/* Bit offsets correspond to the feature number */
 		OHCI_WR(hub->registers->rh_port_status[port], 1 << feature);
Index: uspace/drv/bus/usb/uhci/main.c
===================================================================
--- uspace/drv/bus/usb/uhci/main.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/bus/usb/uhci/main.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -36,5 +36,4 @@
 #include <assert.h>
 #include <ddf/driver.h>
-#include <devman.h>
 #include <errno.h>
 #include <io/log.h>
@@ -123,15 +122,11 @@
 	assert(device);
 
-	async_sess_t *parent_sess = devman_parent_device_connect(
-	    ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
-	if (!parent_sess)
+	async_sess_t *parent_sess = ddf_dev_parent_sess_get(device);
+	if (parent_sess == NULL)
 		return ENOMEM;
 
 	/* See UHCI design guide page 45 for these values.
 	 * Write all WC bits in USB legacy register */
-	const int rc = pci_config_space_write_16(parent_sess, 0xc0, 0xaf00);
-
-	async_hangup(parent_sess);
-	return rc;
+	return pci_config_space_write_16(parent_sess, 0xc0, 0xaf00);
 }
 
Index: uspace/drv/bus/usb/usbhub/status.h
===================================================================
--- uspace/drv/bus/usb/usbhub/status.h	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/bus/usb/usbhub/status.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -35,6 +35,4 @@
 #define	HUB_STATUS_H
 
-#include <stdbool.h>
-#include <stdint.h>
 #include <usb/dev/request.h>
 
Index: uspace/drv/bus/usb/usbhub/usbhub.h
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.h	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/bus/usb/usbhub/usbhub.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -38,5 +38,4 @@
 #define DRV_USBHUB_USBHUB_H
 
-#include <ipc/devman.h>
 #include <ddf/driver.h>
 
@@ -72,5 +71,5 @@
 	/** Condition variable for pending_ops_count. */
 	fibril_condvar_t pending_ops_cv;
-	/** Pointer to devman usbhub function. */
+	/** Pointer to usbhub function. */
 	ddf_fun_t *hub_fun;
 	/** Status indicator */
Index: uspace/drv/bus/usb/usbmid/explore.c
===================================================================
--- uspace/drv/bus/usb/usbmid/explore.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/bus/usb/usbmid/explore.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -132,5 +132,5 @@
  *
  * @param dev Device to be explored.
- * @return Whether to accept this device from devman.
+ * @return Whether to accept this device.
  */
 int usbmid_explore_device(usb_device_t *dev)
Index: uspace/drv/char/atkbd/atkbd.c
===================================================================
--- uspace/drv/char/atkbd/atkbd.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/char/atkbd/atkbd.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -366,5 +366,5 @@
 	
 	kbd->client_sess = NULL;
-	kbd->parent_sess = ddf_dev_parent_sess_create(dev);
+	kbd->parent_sess = ddf_dev_parent_sess_get(dev);
 	
 	if (!kbd->parent_sess) {
Index: uspace/drv/char/atkbd/main.c
===================================================================
--- uspace/drv/char/atkbd/main.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/char/atkbd/main.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -34,5 +34,5 @@
  */
 
-#include <libarch/inttypes.h>
+#include <inttypes.h>
 #include <ddf/driver.h>
 #include <device/hw_res_parsed.h>
Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/char/i8042/i8042.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -269,7 +269,8 @@
 	};
 	
-	rc = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
-	    &irq_code);
-	if (rc != EOK) {
+	const int irq_kbd_cap = register_interrupt_handler(ddf_dev, irq_kbd,
+	    i8042_irq_handler, &irq_code);
+	if (irq_kbd_cap < 0) {
+		rc = irq_kbd_cap;
 		ddf_msg(LVL_ERROR, "Failed set handler for kbd: %s.",
 		    ddf_dev_get_name(ddf_dev));
@@ -277,7 +278,8 @@
 	}
 	
-	rc = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler,
-	    &irq_code);
-	if (rc != EOK) {
+	const int irq_mouse_cap = register_interrupt_handler(ddf_dev, irq_mouse,
+	    i8042_irq_handler, &irq_code);
+	if (irq_mouse_cap < 0) {
+		rc = irq_mouse_cap;
 		ddf_msg(LVL_ERROR, "Failed set handler for mouse: %s.",
 		    ddf_dev_get_name(ddf_dev));
@@ -289,7 +291,15 @@
 	assert(parent_sess != NULL);
 	
-	const bool enabled = hw_res_enable_interrupt(parent_sess);
-	if (!enabled) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to enable interrupts: %s.",
+	rc = hw_res_enable_interrupt(parent_sess, irq_kbd);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to enable keyboard interrupt: %s.",
+		    ddf_dev_get_name(ddf_dev));
+		rc = EIO;
+		goto error;
+	}
+
+	rc = hw_res_enable_interrupt(parent_sess, irq_mouse);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to enable mouse interrupt: %s.",
 		    ddf_dev_get_name(ddf_dev));
 		rc = EIO;
Index: uspace/drv/char/i8042/main.c
===================================================================
--- uspace/drv/char/i8042/main.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/char/i8042/main.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -35,5 +35,5 @@
  */
 
-#include <libarch/inttypes.h>
+#include <inttypes.h>
 #include <libarch/config.h>
 #include <ddf/driver.h>
@@ -60,5 +60,5 @@
 	assert(dev);
 	
-	async_sess_t *parent_sess = ddf_dev_parent_sess_create(dev);
+	async_sess_t *parent_sess = ddf_dev_parent_sess_get(dev);
 	if (parent_sess == NULL)
 		return ENOMEM;
Index: uspace/drv/char/ns8250/ns8250.c
===================================================================
--- uspace/drv/char/ns8250/ns8250.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/char/ns8250/ns8250.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -55,5 +55,4 @@
 #include <ops/char_dev.h>
 
-#include <irc.h>
 #include <device/hw_res.h>
 #include <ipc/serial_ctl.h>
@@ -154,4 +153,6 @@
 	/** DDF function node */
 	ddf_fun_t *fun;
+	/** Parent session */
+	async_sess_t *parent_sess;
 	/** I/O registers **/
 	ns8250_regs_t *regs;
@@ -160,4 +161,6 @@
 	/** The irq assigned to this device. */
 	int irq;
+	/** IRQ capability handle */
+	int irq_cap;
 	/** The base i/o address of the devices registers. */
 	uintptr_t io_addr;
@@ -380,5 +383,4 @@
 static int ns8250_dev_initialize(ns8250_t *ns)
 {
-	async_sess_t *parent_sess;
 	int ret = EOK;
 	
@@ -388,15 +390,6 @@
 	memset(&hw_resources, 0, sizeof(hw_resource_list_t));
 	
-	/* Connect to the parent's driver. */
-	parent_sess = ddf_dev_parent_sess_create(ns->dev);
-	if (parent_sess == NULL) {
-		ddf_msg(LVL_ERROR, "Failed to connect to parent driver of "
-		    "device %s.", ddf_dev_get_name(ns->dev));
-		ret = ENOENT;
-		goto failed;
-	}
-	
 	/* Get hw resources. */
-	ret = hw_res_get_resource_list(parent_sess, &hw_resources);
+	ret = hw_res_get_resource_list(ns->parent_sess, &hw_resources);
 	if (ret != EOK) {
 		ddf_msg(LVL_ERROR, "Failed to get HW resources for device "
@@ -485,5 +478,5 @@
 {
 	/* Enable interrupt using IRC service. */
-	int rc = irc_enable_interrupt(ns->irq);
+	int rc = hw_res_enable_interrupt(ns->parent_sess, ns->irq);
 	if (rc != EOK)
 		return EIO;
@@ -778,5 +771,5 @@
 	
 	ns8250_read_from_device(ns);
-	irc_disable_interrupt(ns->irq);
+	hw_res_clear_interrupt(ns->parent_sess, ns->irq);
 }
 
@@ -797,5 +790,5 @@
 static inline int ns8250_unregister_interrupt_handler(ns8250_t *ns)
 {
-	return unregister_interrupt_handler(ns->dev, ns->irq);
+	return unregister_interrupt_handler(ns->dev, ns->irq_cap);
 }
 
@@ -828,4 +821,12 @@
 	ns->dev = dev;
 	
+	ns->parent_sess = ddf_dev_parent_sess_get(ns->dev);
+	if (ns->parent_sess == NULL) {
+		ddf_msg(LVL_ERROR, "Failed to connect to parent driver of "
+		    "device %s.", ddf_dev_get_name(ns->dev));
+		rc = EIO;
+		goto fail;
+	}
+	
 	rc = ns8250_dev_initialize(ns);
 	if (rc != EOK)
@@ -849,5 +850,6 @@
 	
 	/* Register interrupt handler. */
-	if (ns8250_register_interrupt_handler(ns) != EOK) {
+	ns->irq_cap = ns8250_register_interrupt_handler(ns);
+	if (ns->irq_cap < 0) {
 		ddf_msg(LVL_ERROR, "Failed to register interrupt handler.");
 		rc = EADDRNOTAVAIL;
Index: uspace/drv/char/pl050/pl050.c
===================================================================
--- uspace/drv/char/pl050/pl050.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/char/pl050/pl050.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -38,7 +38,7 @@
 #include <ddf/interrupt.h>
 #include <ddf/log.h>
+#include <device/hw_res.h>
 #include <device/hw_res_parsed.h>
 #include <io/chardev_srv.h>
-#include <irc.h>
 
 #include "pl050_hw.h"
@@ -167,5 +167,5 @@
 	pl050->buf_rp = pl050->buf_wp = 0;
 
-	pl050->parent_sess = ddf_dev_parent_sess_create(pl050->dev);
+	pl050->parent_sess = ddf_dev_parent_sess_get(pl050->dev);
 	if (pl050->parent_sess == NULL) {
 		ddf_msg(LVL_ERROR, "Failed connecitng parent driver.");
@@ -212,7 +212,8 @@
 	pl050->regs = regs;
 
-	rc = register_interrupt_handler(pl050->dev, res.irqs.irqs[0],
-	    pl050_interrupt, &pl050_irq_code);
-	if (rc != EOK) {
+	const int irq_cap = register_interrupt_handler(pl050->dev,
+	    res.irqs.irqs[0], pl050_interrupt, &pl050_irq_code);
+	if (irq_cap < 0) {
+		rc = irq_cap;
 		ddf_msg(LVL_ERROR, "Failed registering interrupt handler. (%d)",
 		    rc);
@@ -220,5 +221,5 @@
 	}
 
-	rc = irc_enable_interrupt(res.irqs.irqs[0]);
+	rc = hw_res_enable_interrupt(pl050->parent_sess, res.irqs.irqs[0]);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed enabling interrupt. (%d)", rc);
Index: uspace/drv/char/ps2mouse/main.c
===================================================================
--- uspace/drv/char/ps2mouse/main.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/char/ps2mouse/main.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -33,5 +33,5 @@
  */
 
-#include <libarch/inttypes.h>
+#include <inttypes.h>
 #include <ddf/driver.h>
 #include <device/hw_res_parsed.h>
Index: uspace/drv/char/ps2mouse/ps2mouse.c
===================================================================
--- uspace/drv/char/ps2mouse/ps2mouse.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/char/ps2mouse/ps2mouse.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -116,5 +116,5 @@
 {
 	mouse->client_sess = NULL;
-	mouse->parent_sess = ddf_dev_parent_sess_create(dev);
+	mouse->parent_sess = ddf_dev_parent_sess_get(dev);
 	if (!mouse->parent_sess)
 		return ENOMEM;
Index: uspace/drv/char/xtkbd/main.c
===================================================================
--- uspace/drv/char/xtkbd/main.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/char/xtkbd/main.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -34,5 +34,5 @@
  */
 
-#include <libarch/inttypes.h>
+#include <inttypes.h>
 #include <ddf/driver.h>
 #include <device/hw_res_parsed.h>
Index: uspace/drv/char/xtkbd/xtkbd.c
===================================================================
--- uspace/drv/char/xtkbd/xtkbd.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/char/xtkbd/xtkbd.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -417,5 +417,5 @@
 	
 	kbd->client_sess = NULL;
-	kbd->parent_sess = ddf_dev_parent_sess_create(dev);
+	kbd->parent_sess = ddf_dev_parent_sess_get(dev);
 	
 	if (!kbd->parent_sess) {
Index: uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.c
===================================================================
--- uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -267,5 +267,5 @@
 	amdm37x_dispc_t *dispc = vis->dev_ctx;
 	const visual_t visual = mode.cell_visual.pixel_visual;
-	assert(visual < sizeof(pixel2visual_table) / sizeof(pixel2visual_table[0]));
+	assert((size_t)visual < sizeof(pixel2visual_table) / sizeof(pixel2visual_table[0]));
 	const unsigned bpp = pixel2visual_table[visual].bpp;
 	pixel2visual_t p2v = pixel2visual_table[visual].func;
Index: uspace/drv/fb/amdm37x_dispc/main.c
===================================================================
--- uspace/drv/fb/amdm37x_dispc/main.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/fb/amdm37x_dispc/main.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -91,5 +91,5 @@
 	}
 
-	/* Report to devman */
+	/* Bind function */
 	ret = ddf_fun_bind(fun);
 	if (ret != EOK) {
Index: uspace/drv/fb/kfb/port.c
===================================================================
--- uspace/drv/fb/kfb/port.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/fb/kfb/port.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -66,4 +66,5 @@
 
 typedef struct {
+	sysarg_t paddr;
 	sysarg_t width;
 	sysarg_t height;
@@ -85,71 +86,24 @@
 static vslmode_list_element_t pixel_mode;
 
-static pixel_t color_table[16] = {
-	[COLOR_BLACK]       = 0x000000,
-	[COLOR_BLUE]        = 0x0000f0,
-	[COLOR_GREEN]       = 0x00f000,
-	[COLOR_CYAN]        = 0x00f0f0,
-	[COLOR_RED]         = 0xf00000,
-	[COLOR_MAGENTA]     = 0xf000f0,
-	[COLOR_YELLOW]      = 0xf0f000,
-	[COLOR_WHITE]       = 0xf0f0f0,
-
-	[COLOR_BLACK + 8]   = 0x000000,
-	[COLOR_BLUE + 8]    = 0x0000ff,
-	[COLOR_GREEN + 8]   = 0x00ff00,
-	[COLOR_CYAN + 8]    = 0x00ffff,
-	[COLOR_RED + 8]     = 0xff0000,
-	[COLOR_MAGENTA + 8] = 0xff00ff,
-	[COLOR_YELLOW + 8]  = 0xffff00,
-	[COLOR_WHITE + 8]   = 0xffffff,
-};
-
-static inline void attrs_rgb(char_attrs_t attrs, pixel_t *bgcolor, pixel_t *fgcolor)
-{
-	switch (attrs.type) {
-	case CHAR_ATTR_STYLE:
-		switch (attrs.val.style) {
-		case STYLE_NORMAL:
-			*bgcolor = color_table[COLOR_WHITE];
-			*fgcolor = color_table[COLOR_BLACK];
-			break;
-		case STYLE_EMPHASIS:
-			*bgcolor = color_table[COLOR_WHITE];
-			*fgcolor = color_table[COLOR_RED];
-			break;
-		case STYLE_INVERTED:
-			*bgcolor = color_table[COLOR_BLACK];
-			*fgcolor = color_table[COLOR_WHITE];
-			break;
-		case STYLE_SELECTED:
-			*bgcolor = color_table[COLOR_RED];
-			*fgcolor = color_table[COLOR_WHITE];
-			break;
-		}
-		break;
-	case CHAR_ATTR_INDEX:
-		*bgcolor = color_table[(attrs.val.index.bgcolor & 7) |
-		    ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
-		*fgcolor = color_table[(attrs.val.index.fgcolor & 7) |
-		    ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
-		break;
-	case CHAR_ATTR_RGB:
-		*bgcolor = attrs.val.rgb.bgcolor;
-		*fgcolor = attrs.val.rgb.fgcolor;
-		break;
-	}
-}
-
 static int kfb_claim(visualizer_t *vs)
 {
-	return EOK;
+	return physmem_map(kfb.paddr + kfb.offset,
+	    ALIGN_UP(kfb.size, PAGE_SIZE) >> PAGE_WIDTH,
+	    AS_AREA_READ | AS_AREA_WRITE, (void *) &kfb.addr);
 }
 
 static int kfb_yield(visualizer_t *vs)
 {
+	int rc;
+
 	if (vs->mode_set) {
 		vs->ops.handle_damage = NULL;
 	}
 
+	rc = physmem_unmap(kfb.addr);
+	if (rc != EOK)
+		return rc;
+
+	kfb.addr = NULL;
 	return EOK;
 }
@@ -211,7 +165,14 @@
 {
 	visualizer_t *vsl;
+	int rc;
 
 	vsl = (visualizer_t *) ddf_fun_data_get((ddf_fun_t *)arg);
 	graph_visualizer_connection(vsl, iid, icall, NULL);
+
+	if (kfb.addr != NULL) {
+		rc = physmem_unmap(kfb.addr);
+		if (rc == EOK)
+			kfb.addr = NULL;
+	}
 }
 
@@ -266,4 +227,5 @@
 	kfb.width = width;
 	kfb.height = height;
+	kfb.paddr = paddr;
 	kfb.offset = offset;
 	kfb.scanline = scanline;
@@ -343,10 +305,4 @@
 	kfb.size = scanline * height;
 	kfb.addr = AS_AREA_ANY;
-	
-	rc = physmem_map(paddr + offset,
-	    ALIGN_UP(kfb.size, PAGE_SIZE) >> PAGE_WIDTH,
-	    AS_AREA_READ | AS_AREA_WRITE, (void *) &kfb.addr);
-	if (rc != EOK)
-		return rc;
 	
 	ddf_fun_t *fun_vs = ddf_fun_create(dev, fun_exposed, "vsl0");
Index: uspace/drv/intctl/icp-ic/Makefile
===================================================================
--- uspace/drv/intctl/icp-ic/Makefile	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/intctl/icp-ic/Makefile	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2014 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = icp-ic
+
+SOURCES = \
+	icp-ic.c \
+	main.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/intctl/icp-ic/icp-ic.c
===================================================================
--- uspace/drv/intctl/icp-ic/icp-ic.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/intctl/icp-ic/icp-ic.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2014 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup icp-ic
+ * @{
+ */
+
+/**
+ * @file icp-ic.c
+ * @brief IntegratorCP interrupt controller driver
+ */
+
+#include <async.h>
+#include <bitops.h>
+#include <ddi.h>
+#include <ddf/log.h>
+#include <errno.h>
+#include <ipc/irc.h>
+#include <loc.h>
+#include <stdint.h>
+
+#include "icp-ic.h"
+#include "icp-ic_hw.h"
+
+enum {
+	icpic_max_irq = 32
+};
+
+static int icpic_enable_irq(icpic_t *icpic, sysarg_t irq)
+{
+	if (irq > icpic_max_irq)
+		return EINVAL;
+
+	ddf_msg(LVL_NOTE, "Enable IRQ %zu", irq);
+
+	pio_write_32(&icpic->regs->irq_enableset, BIT_V(uint32_t, irq));
+	return EOK;
+}
+
+/** Client connection handler.
+ *
+ * @param iid   Hash of the request that opened the connection.
+ * @param icall Call data of the request that opened the connection.
+ * @param arg	Local argument.
+ */
+static void icpic_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ipc_callid_t callid;
+	ipc_call_t call;
+	icpic_t *icpic;
+
+	/*
+	 * Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	async_answer_0(iid, EOK);
+
+	icpic = (icpic_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg));
+
+	while (true) {
+		callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call)) {
+			/* The other side has hung up. */
+			async_answer_0(callid, EOK);
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case IRC_ENABLE_INTERRUPT:
+			async_answer_0(callid,
+			    icpic_enable_irq(icpic, IPC_GET_ARG1(call)));
+			break;
+		case IRC_DISABLE_INTERRUPT:
+			/* XXX TODO */
+			async_answer_0(callid, EOK);
+			break;
+		case IRC_CLEAR_INTERRUPT:
+			/* Noop */
+			async_answer_0(callid, EOK);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+			break;
+		}
+	}
+}
+
+/** Add icp-ic device. */
+int icpic_add(icpic_t *icpic, icpic_res_t *res)
+{
+	ddf_fun_t *fun_a = NULL;
+	void *regs;
+	int rc;
+
+	rc = pio_enable((void *)res->base, sizeof(icpic_regs_t), &regs);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Error enabling PIO");
+		goto error;
+	}
+
+	icpic->regs = (icpic_regs_t *)regs;
+
+	fun_a = ddf_fun_create(icpic->dev, fun_exposed, "a");
+	if (fun_a == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	ddf_fun_set_conn_handler(fun_a, icpic_connection);
+
+	rc = ddf_fun_bind(fun_a);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function 'a'. (%d)", rc);
+		goto error;
+	}
+
+	rc = ddf_fun_add_to_category(fun_a, "irc");
+	if (rc != EOK)
+		goto error;
+
+	return EOK;
+error:
+	if (fun_a != NULL)
+		ddf_fun_destroy(fun_a);
+	return rc;
+}
+
+/** Remove icp-ic device */
+int icpic_remove(icpic_t *icpic)
+{
+	return ENOTSUP;
+}
+
+/** icp-ic device gone */
+int icpic_gone(icpic_t *icpic)
+{
+	return ENOTSUP;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/intctl/icp-ic/icp-ic.h
===================================================================
--- uspace/drv/intctl/icp-ic/icp-ic.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/intctl/icp-ic/icp-ic.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ICP_IC_H_
+#define ICP_IC_H
+
+#include <ddf/driver.h>
+#include <loc.h>
+#include <stdint.h>
+
+#include "icp-ic_hw.h"
+
+typedef struct {
+	uintptr_t base;
+} icpic_res_t;
+
+/** IntegratorCP Interrupt Controller */
+typedef struct {
+	icpic_regs_t *regs;
+	uintptr_t phys_base;
+	ddf_dev_t *dev;
+} icpic_t;
+
+extern int icpic_add(icpic_t *, icpic_res_t *);
+extern int icpic_remove(icpic_t *);
+extern int icpic_gone(icpic_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/drv/intctl/icp-ic/icp-ic.ma
===================================================================
--- uspace/drv/intctl/icp-ic/icp-ic.ma	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/intctl/icp-ic/icp-ic.ma	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -0,0 +1,1 @@
+10 integratorcp/intctl
Index: uspace/drv/intctl/icp-ic/icp-ic_hw.h
===================================================================
--- uspace/drv/intctl/icp-ic/icp-ic_hw.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/intctl/icp-ic/icp-ic_hw.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup pl050
+ * @{
+ */
+/** @file ARM PrimeCell PS2 Keyboard/Mouse Interface (PL050) registers
+ */
+
+#ifndef ICP_IC_HW_H
+#define ICP_IC_HW_H
+
+#include <ddi.h>
+
+typedef struct {
+	ioport32_t irq_status;
+	ioport32_t irq_rawstat;
+	ioport32_t irq_enableset;
+	ioport32_t irq_enableclr;
+	ioport32_t int_softset;
+	ioport32_t int_softclr;
+	ioport32_t fiq_status;
+	ioport32_t fiq_rawstat;
+	ioport32_t fiq_enableset;
+	ioport32_t fiq_enableclr;
+} icpic_regs_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/drv/intctl/icp-ic/main.c
===================================================================
--- uspace/drv/intctl/icp-ic/main.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/intctl/icp-ic/main.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2017 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/** @file IntegratorCP Interrupt Controller driver
+ */
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <device/hw_res_parsed.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "icp-ic.h"
+
+#define NAME  "icp-ic"
+
+static int icpic_dev_add(ddf_dev_t *dev);
+static int icpic_dev_remove(ddf_dev_t *dev);
+static int icpic_dev_gone(ddf_dev_t *dev);
+static int icpic_fun_online(ddf_fun_t *fun);
+static int icpic_fun_offline(ddf_fun_t *fun);
+
+static driver_ops_t driver_ops = {
+	.dev_add = icpic_dev_add,
+	.dev_remove = icpic_dev_remove,
+	.dev_gone = icpic_dev_gone,
+	.fun_online = icpic_fun_online,
+	.fun_offline = icpic_fun_offline
+};
+
+static driver_t icpic_driver = {
+	.name = NAME,
+	.driver_ops = &driver_ops
+};
+
+static int icpic_get_res(ddf_dev_t *dev, icpic_res_t *res)
+{
+	async_sess_t *parent_sess;
+	hw_res_list_parsed_t hw_res;
+	int rc;
+
+	parent_sess = ddf_dev_parent_sess_get(dev);
+	if (parent_sess == NULL)
+		return ENOMEM;
+
+	hw_res_list_parsed_init(&hw_res);
+	rc = hw_res_get_list_parsed(parent_sess, &hw_res, 0);
+	if (rc != EOK)
+		return rc;
+
+	if (hw_res.mem_ranges.count != 1) {
+		rc = EINVAL;
+		goto error;
+	}
+
+	res->base = RNGABS(hw_res.mem_ranges.ranges[0]);
+
+	return EOK;
+error:
+	hw_res_list_parsed_clean(&hw_res);
+	return rc;
+}
+
+static int icpic_dev_add(ddf_dev_t *dev)
+{
+	icpic_t *icpic;
+	icpic_res_t icpic_res;
+	int rc;
+
+        ddf_msg(LVL_DEBUG, "icpic_dev_add(%p)", dev);
+	icpic = ddf_dev_data_alloc(dev, sizeof(icpic_t));
+	if (icpic == NULL) {
+		ddf_msg(LVL_ERROR, "Failed allocating soft state.");
+		return ENOMEM;
+	}
+
+	icpic->dev = dev;
+
+	rc = icpic_get_res(dev, &icpic_res);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed getting hardware resource list.\n");
+		return EIO;
+	}
+
+	return icpic_add(icpic, &icpic_res);
+}
+
+static int icpic_dev_remove(ddf_dev_t *dev)
+{
+        icpic_t *icpic = (icpic_t *)ddf_dev_data_get(dev);
+
+        ddf_msg(LVL_DEBUG, "icpic_dev_remove(%p)", dev);
+
+        return icpic_remove(icpic);
+}
+
+static int icpic_dev_gone(ddf_dev_t *dev)
+{
+        icpic_t *icpic = (icpic_t *)ddf_dev_data_get(dev);
+
+        ddf_msg(LVL_DEBUG, "icpic_dev_gone(%p)", dev);
+
+        return icpic_gone(icpic);
+}
+
+static int icpic_fun_online(ddf_fun_t *fun)
+{
+        ddf_msg(LVL_DEBUG, "icpic_fun_online()");
+        return ddf_fun_online(fun);
+}
+
+static int icpic_fun_offline(ddf_fun_t *fun)
+{
+        ddf_msg(LVL_DEBUG, "icpic_fun_offline()");
+        return ddf_fun_offline(fun);
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": IntegratorCP Interrupt Controller driver\n");
+	ddf_log_init(NAME);
+	return ddf_driver_main(&icpic_driver);
+}
+
+/** @}
+ */
Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/nic/e1k/e1k.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -40,9 +40,9 @@
 #include <thread.h>
 #include <byteorder.h>
-#include <irc.h>
 #include <as.h>
 #include <ddi.h>
 #include <ddf/log.h>
 #include <ddf/interrupt.h>
+#include <device/hw_res.h>
 #include <device/hw_res_parsed.h>
 #include <pci_dev_iface.h>
@@ -116,4 +116,8 @@
 /** E1000 device data */
 typedef struct {
+	/** DDF device */
+	ddf_dev_t *dev;
+	/** Parent session */
+	async_sess_t *parent_sess;
 	/** Device configuration */
 	e1000_info_t info;
@@ -365,13 +369,16 @@
 	if (ctrl & CTRL_SLU) {
 		ctrl &= ~(CTRL_SLU);
+		E1000_REG_WRITE(e1000, E1000_CTRL, ctrl);
 		fibril_mutex_unlock(&e1000->ctrl_lock);
+		
 		thread_usleep(10);
+		
 		fibril_mutex_lock(&e1000->ctrl_lock);
+		ctrl = E1000_REG_READ(e1000, E1000_CTRL);
 		ctrl |= CTRL_SLU;
+		E1000_REG_WRITE(e1000, E1000_CTRL, ctrl);
 	}
 	
 	fibril_mutex_unlock(&e1000->ctrl_lock);
-	
-	e1000_link_restart(e1000);
 }
 
@@ -1253,5 +1260,5 @@
  * @param nic Driver data
  *
- * @return EOK if the handler was registered
+ * @return IRQ capability handle if the handler was registered
  * @return Negative error code otherwise
  *
@@ -1268,9 +1275,9 @@
 	e1000_irq_code.cmds[2].addr = e1000->reg_base_phys + E1000_IMC;
 	
-	int rc = register_interrupt_handler(nic_get_ddf_dev(nic),
-	    e1000->irq, e1000_interrupt_handler, &e1000_irq_code);
+	int cap = register_interrupt_handler(nic_get_ddf_dev(nic), e1000->irq,
+	    e1000_interrupt_handler, &e1000_irq_code);
 	
 	fibril_mutex_unlock(&irq_reg_mutex);
-	return rc;
+	return cap;
 }
 
@@ -1754,5 +1761,5 @@
 	e1000_enable_interrupts(e1000);
 	
-	int rc = irc_enable_interrupt(e1000->irq);
+	int rc = hw_res_enable_interrupt(e1000->parent_sess, e1000->irq);
 	if (rc != EOK) {
 		e1000_disable_interrupts(e1000);
@@ -1799,5 +1806,5 @@
 	e1000_disable_rx(e1000);
 	
-	irc_disable_interrupt(e1000->irq);
+	hw_res_disable_interrupt(e1000->parent_sess, e1000->irq);
 	e1000_disable_interrupts(e1000);
 	
@@ -1881,4 +1888,5 @@
 	
 	memset(e1000, 0, sizeof(e1000_t));
+	e1000->dev = dev;
 	
 	nic_set_specific(nic, e1000);
@@ -1995,4 +2003,10 @@
 		ddf_msg(LVL_ERROR, "Unable to allocate device softstate");
 		return ENOMEM;
+	}
+	
+	e1000->parent_sess = ddf_dev_parent_sess_get(dev);
+	if (e1000->parent_sess == NULL) {
+		ddf_msg(LVL_ERROR, "Failed connecting parent device.");
+		return EIO;
 	}
 	
@@ -2116,5 +2130,4 @@
 {
 	ddf_fun_t *fun;
-	assert(dev);
 	
 	/* Initialize device structure for E1000 */
@@ -2152,7 +2165,9 @@
 	ddf_fun_set_ops(fun, &e1000_dev_ops);
 	
-	rc = e1000_register_int_handler(nic);
-	if (rc != EOK)
+	int irq_cap = e1000_register_int_handler(nic);
+	if (irq_cap < 0) {
+		rc = irq_cap;
 		goto err_fun_create;
+	}
 	
 	rc = e1000_initialize_rx_structure(nic);
@@ -2189,5 +2204,5 @@
 	e1000_uninitialize_rx_structure(nic);
 err_irq:
-	unregister_interrupt_handler(dev, DRIVER_DATA_DEV(dev)->irq);
+	unregister_interrupt_handler(dev, irq_cap);
 err_fun_create:
 	ddf_fun_destroy(fun);
Index: uspace/drv/nic/ne2k/dp8390.h
===================================================================
--- uspace/drv/nic/ne2k/dp8390.h	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/nic/ne2k/dp8390.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -50,4 +50,6 @@
 #define __NET_NETIF_DP8390_H__
 
+#include <async.h>
+#include <ddf/driver.h>
 #include <fibril_synch.h>
 #include <nic.h>
@@ -223,4 +225,8 @@
 
 typedef struct {
+	/** DDF device */
+	ddf_dev_t *dev;
+	/** Parent session */
+	async_sess_t *parent_sess;
 	/* Device configuration */
 	void *base_port; /**< Port assigned from ISA configuration **/
Index: uspace/drv/nic/ne2k/ne2k.c
===================================================================
--- uspace/drv/nic/ne2k/ne2k.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -40,5 +40,5 @@
 #include <stdio.h>
 #include <errno.h>
-#include <irc.h>
+#include <device/hw_res.h>
 #include <stdlib.h>
 #include <str_error.h>
@@ -160,7 +160,7 @@
 	}
 
-	int rc = register_interrupt_handler(nic_get_ddf_dev(nic_data),
+	int irq_cap = register_interrupt_handler(nic_get_ddf_dev(nic_data),
 		ne2k->irq, ne2k_interrupt_handler, &ne2k->code);
-	return rc;
+	return irq_cap;
 }
 
@@ -228,6 +228,6 @@
 	ne2k->probed = true;
 	
-	rc = ne2k_register_interrupt(nic_data);
-	if (rc != EOK)
+	int irq_cap = ne2k_register_interrupt(nic_data);
+	if (irq_cap < 0)
 		return EINVAL;
 	
@@ -256,5 +256,5 @@
 			return rc;
 
-		rc = irc_enable_interrupt(ne2k->irq);
+		rc = hw_res_enable_interrupt(ne2k->parent_sess, ne2k->irq);
 		if (rc != EOK) {
 			ne2k_down(ne2k);
@@ -269,5 +269,5 @@
 	ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data);
 
-	(void) irc_disable_interrupt(ne2k->irq);
+	(void) hw_res_disable_interrupt(ne2k->parent_sess, ne2k->irq);
 	ne2k->receive_configuration = RCR_AB | RCR_AM;
 	ne2k_down(ne2k);
@@ -384,4 +384,11 @@
 	}
 	
+	ne2k->dev = dev;
+	ne2k->parent_sess = ddf_dev_parent_sess_get(dev);
+	if (ne2k->parent_sess == NULL) {
+		ne2k_dev_cleanup(dev);
+		return ENOMEM;
+	}
+	
 	int rc = ne2k_dev_init(nic_data);
 	if (rc != EOK) {
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/nic/rtl8139/driver.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -36,8 +36,8 @@
 #include <ddf/log.h>
 #include <ddf/interrupt.h>
+#include <device/hw_res.h>
 #include <io/log.h>
 #include <nic.h>
 #include <pci_dev_iface.h>
-#include <irc.h>
 #include <stdio.h>
 #include <str.h>
@@ -125,17 +125,9 @@
 
 
-/** Disable interrupts on controller
+/** Set interrupts on controller
  *
  *  @param rtl8139  The card private structure
  */
-inline static void rtl8139_hw_int_disable(rtl8139_t *rtl8139)
-{
-	pio_write_16(rtl8139->io_port + IMR, 0x0);
-}
-/** Enable interrupts on controller
- *
- *  @param rtl8139  The card private structure
- */
-inline static void rtl8139_hw_int_enable(rtl8139_t *rtl8139)
+inline static void rtl8139_hw_int_set(rtl8139_t *rtl8139)
 {
 	pio_write_16(rtl8139->io_port + IMR, rtl8139->int_mask);
@@ -274,18 +266,4 @@
 }
 
-/**  Provide OR in the 32bit register (set selected bits to 1)
- *
- *   @param rtl8139     The rtl8139 structure
- *   @param reg_offset  Register offset in the device IO space
- *   @param bits_add    The value to or
- */
-inline static void rtl8139_hw_reg_add_32(rtl8139_t * rtl8139, size_t reg_offset,
-    uint32_t bits_add)
-{
-	uint32_t value = pio_read_32(rtl8139->io_port + reg_offset);
-	value |= bits_add;
-	pio_write_32(rtl8139->io_port + reg_offset, value);
-}
-
 /**  Unset selected bits in 8bit register
  *
@@ -301,19 +279,4 @@
 	pio_write_8(rtl8139->io_port + reg_offset, value);
 }
-
-/**  Unset selected bits in 32bit register
- *
- *   @param rtl8139     The rtl8139 structure
- *   @param reg_offset  Register offset in the device IO space
- *   @param bits_add    The mask of bits to remove
- */
-inline static void rtl8139_hw_reg_rem_32(rtl8139_t * rtl8139, size_t reg_offset,
-    uint32_t bits_add)
-{
-	uint32_t value = pio_read_32(rtl8139->io_port + reg_offset);
-	value &= ~bits_add;
-	pio_write_32(rtl8139->io_port + reg_offset, value);
-}
-
 
 static int rtl8139_set_addr(ddf_fun_t *fun, const nic_address_t *);
@@ -871,5 +834,5 @@
 
 	/* Turn the interrupts on again */
-	rtl8139_hw_int_enable(rtl8139);
+	rtl8139_hw_int_set(rtl8139);
 };
 
@@ -881,5 +844,6 @@
  *  @param nic_data  The driver data
  *
- *  @return EOK if the handler was registered, negative error code otherwise
+ *  @return IRQ capability handle if the handler was registered.
+ *  @return Negative error code otherwise.
  */
 inline static int rtl8139_register_int_handler(nic_t *nic_data)
@@ -894,10 +858,10 @@
 	rtl8139_irq_code.cmds[2].addr = rtl8139->io_addr + ISR;
 	rtl8139_irq_code.cmds[3].addr = rtl8139->io_addr + IMR;
-	int rc = register_interrupt_handler(nic_get_ddf_dev(nic_data),
+	int cap = register_interrupt_handler(nic_get_ddf_dev(nic_data),
 	    rtl8139->irq, rtl8139_interrupt_handler, &rtl8139_irq_code);
 
 	RTL8139_IRQ_STRUCT_UNLOCK();
 
-	return rc;
+	return cap;
 }
 
@@ -954,7 +918,7 @@
 
 	rtl8139->int_mask = RTL_DEFAULT_INTERRUPTS;
-	rtl8139_hw_int_enable(rtl8139);
-
-	int rc = irc_enable_interrupt(rtl8139->irq);
+	rtl8139_hw_int_set(rtl8139);
+
+	int rc = hw_res_enable_interrupt(rtl8139->parent_sess, rtl8139->irq);
 	if (rc != EOK) {
 		rtl8139_on_stopped(nic_data);
@@ -1012,5 +976,5 @@
 		return NULL;
 
-	rtl8139_t *rtl8139 = malloc(sizeof(rtl8139_t));
+	rtl8139_t *rtl8139 = calloc(1, sizeof(rtl8139_t));
 	if (!rtl8139) {
 		nic_unbind_and_destroy(dev);
@@ -1018,5 +982,5 @@
 	}
 
-	memset(rtl8139, 0, sizeof(rtl8139_t));
+	rtl8139->dev = dev;
 
 	rtl8139->nic_data = nic_data;
@@ -1202,4 +1166,9 @@
 
 	ddf_msg(LVL_DEBUG, "rtl8139: dev_data created");
+	rtl8139->parent_sess = ddf_dev_parent_sess_get(dev);
+	if (rtl8139->parent_sess == NULL) {
+		ddf_msg(LVL_ERROR, "Error connecting parent device.");
+		return EIO;
+	}
 
 	/* Obtain and fill hardware resources info and connect to parent */
@@ -1294,5 +1263,4 @@
 	ddf_fun_t *fun;
 
-	assert(dev);
 	ddf_msg(LVL_NOTE, "RTL8139_dev_add %s (handle = %zu)",
 	    ddf_dev_get_name(dev), ddf_dev_get_handle(dev));
@@ -1321,7 +1289,9 @@
 
 	/* Register interrupt handler */
-	rc = rtl8139_register_int_handler(nic_data);
-	if (rc != EOK)
+	int irq_cap = rtl8139_register_int_handler(nic_data);
+	if (irq_cap < 0) {
+		rc = irq_cap;
 		goto err_pio;
+	}
 
 	fun = ddf_fun_create(nic_get_ddf_dev(nic_data), fun_exposed, "port0");
@@ -1355,5 +1325,5 @@
 	ddf_fun_destroy(fun);
 err_srv:
-	unregister_interrupt_handler(dev, rtl8139->irq);
+	unregister_interrupt_handler(dev, irq_cap);
 err_pio:
 	// rtl8139_pio_disable(dev);
@@ -2117,5 +2087,5 @@
 		/* Disable timer interrupts while working with timer-related data */
 		rtl8139->int_mask = 0;
-		rtl8139_hw_int_enable(rtl8139);
+		rtl8139_hw_int_set(rtl8139);
 
 		rtl8139->poll_timer = new_timer;
@@ -2140,5 +2110,5 @@
 	}
 
-	rtl8139_hw_int_enable(rtl8139);
+	rtl8139_hw_int_set(rtl8139);
 
 	fibril_mutex_unlock(&rtl8139->rx_lock);
Index: uspace/drv/nic/rtl8139/driver.h
===================================================================
--- uspace/drv/nic/rtl8139/driver.h	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/nic/rtl8139/driver.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -87,4 +87,8 @@
 /** RTL8139 device data */
 typedef struct rtl8139_data {
+	/** DDF device */
+	ddf_dev_t *dev;
+	/** Parent session */
+	async_sess_t *parent_sess;
 	/** I/O address of the device */
 	void *io_addr;
Index: uspace/drv/nic/rtl8169/driver.c
===================================================================
--- uspace/drv/nic/rtl8169/driver.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/nic/rtl8169/driver.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -31,5 +31,4 @@
 #include <align.h>
 #include <byteorder.h>
-#include <irc.h>
 #include <libarch/barrier.h>
 
@@ -38,9 +37,10 @@
 #include <ddf/log.h>
 #include <ddf/interrupt.h>
+#include <device/hw_res.h>
+#include <device/hw_res_parsed.h>
 #include <io/log.h>
 #include <nic.h>
 #include <pci_dev_iface.h>
 
-#include <ipc/irc.h>
 #include <sysinfo.h>
 #include <ipc/ns.h>
@@ -371,8 +371,8 @@
 	rtl8169_irq_code.cmds[2].addr = rtl8169->regs + ISR;
 	rtl8169_irq_code.cmds[3].addr = rtl8169->regs + IMR;
-	int rc = register_interrupt_handler(nic_get_ddf_dev(nic_data),
+	int irq_cap = register_interrupt_handler(nic_get_ddf_dev(nic_data),
 	    rtl8169->irq, rtl8169_irq_handler, &rtl8169_irq_code);
 
-	return rc;
+	return irq_cap;
 }
 
@@ -396,12 +396,17 @@
 	rtl8169_t *rtl8169 = nic_get_specific(nic_data);
 
+	rtl8169->dev = dev;
+	rtl8169->parent_sess = ddf_dev_parent_sess_get(dev);
+	if (rtl8169->parent_sess == NULL)
+		return EIO;
+
 	/* Get PCI VID & PID */
-	rc = pci_config_space_read_16(ddf_dev_parent_sess_get(dev),
-	    PCI_VENDOR_ID, &rtl8169->pci_vid);
+	rc = pci_config_space_read_16(rtl8169->parent_sess, PCI_VENDOR_ID,
+	    &rtl8169->pci_vid);
 	if (rc != EOK)
 		return rc;
 
-	rc = pci_config_space_read_16(ddf_dev_parent_sess_get(dev),
-	    PCI_DEVICE_ID, &rtl8169->pci_pid);
+	rc = pci_config_space_read_16(rtl8169->parent_sess, PCI_DEVICE_ID,
+	    &rtl8169->pci_pid);
 	if (rc != EOK)
 		return rc;
@@ -426,9 +431,9 @@
 		goto err_pio;
 
-	rc = rtl8169_register_int_handler(nic_data);
-	if (rc != EOK) {
+	int irq_cap = rtl8169_register_int_handler(nic_data);
+	if (irq_cap < 0) {
+		rc = irq_cap;
 		ddf_msg(LVL_ERROR, "Failed to register IRQ handler (%d)", rc);
 		goto err_irq;
-
 	}
 
@@ -469,6 +474,6 @@
 err_srv:
 	/* XXX Disconnect from services */
+	unregister_interrupt_handler(dev, irq_cap);
 err_irq:
-	//unregister_interrupt_handler(dev, rtl8169->irq);
 err_pio:
 err_destroy:
@@ -745,5 +750,6 @@
 
 	pio_write_16(rtl8169->regs + IMR, 0xffff);
-	irc_enable_interrupt(rtl8169->irq);
+	/* XXX Check return value */
+	hw_res_enable_interrupt(rtl8169->parent_sess, rtl8169->irq);
 
 	return EOK;
Index: uspace/drv/nic/rtl8169/driver.h
===================================================================
--- uspace/drv/nic/rtl8169/driver.h	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/nic/rtl8169/driver.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -49,4 +49,8 @@
 /** RTL8139 device data */
 typedef struct rtl8169_data {
+	/** DDF device */
+	ddf_dev_t *dev;
+	/** Parent session */
+	async_sess_t *parent_sess;
 	/** I/O address of the device */
 	void *regs_phys;
Index: uspace/drv/platform/amdm37x/main.c
===================================================================
--- uspace/drv/platform/amdm37x/main.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/platform/amdm37x/main.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -150,5 +150,5 @@
 
 static hw_resource_list_t *amdm37x_get_resources(ddf_fun_t *fnode);
-static bool amdm37x_enable_interrupt(ddf_fun_t *fun);
+static int amdm37x_enable_interrupt(ddf_fun_t *fun, int);
 
 static hw_res_ops_t fun_hw_res_ops = {
@@ -265,5 +265,5 @@
 }
 
-static bool amdm37x_enable_interrupt(ddf_fun_t *fun)
+static int amdm37x_enable_interrupt(ddf_fun_t *fun, int irq)
 {
 	//TODO: Implement
Index: uspace/drv/platform/icp/icp.c
===================================================================
--- uspace/drv/platform/icp/icp.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/platform/icp/icp.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -39,4 +39,5 @@
 #include <stdio.h>
 #include <errno.h>
+#include <irc.h>
 #include <stdbool.h>
 #include <stdlib.h>
@@ -53,5 +54,6 @@
 	icp_kbd_irq = 3,
 	icp_mouse_base = 0x19000000,
-	icp_mouse_irq = 4
+	icp_mouse_irq = 4,
+	icp_ic_base = 0x14000000
 };
 
@@ -107,4 +109,16 @@
 };
 
+static hw_resource_t icp_ic_res[] = {
+	{
+		.type = MEM_RANGE,
+		.res.mem_range = {
+			.address = icp_ic_base,
+			.size = 40,
+			.relative = false,
+			.endianness = LITTLE_ENDIAN
+		}
+	}
+};
+
 static pio_window_t icp_pio_window = {
 	.mem = {
@@ -128,4 +142,11 @@
 };
 
+static icp_fun_t icp_ic_fun_proto = {
+	.hw_resources = {
+		sizeof(icp_ic_res) / sizeof(icp_ic_res[0]),
+		icp_ic_res
+	},
+};
+
 /** Obtain function soft-state from DDF function node */
 static icp_fun_t *icp_fun(ddf_fun_t *fnode)
@@ -142,8 +163,47 @@
 }
 
-static bool icp_enable_interrupt(ddf_fun_t *fun)
-{
-	/* TODO */
+static bool icp_fun_owns_interrupt(icp_fun_t *fun, int irq)
+{
+	const hw_resource_list_t *res = &fun->hw_resources;
+
+	/* Check that specified irq really belongs to the function */
+	for (size_t i = 0; i < res->count; ++i) {
+		if (res->resources[i].type == INTERRUPT &&
+		    res->resources[i].res.interrupt.irq == irq) {
+			return true;
+		}
+	}
+
 	return false;
+}
+
+static int icp_fun_enable_interrupt(ddf_fun_t *fnode, int irq)
+{
+	icp_fun_t *fun = icp_fun(fnode);
+
+	if (!icp_fun_owns_interrupt(fun, irq))
+		return EINVAL;
+
+	return irc_enable_interrupt(irq);
+}
+
+static int icp_fun_disable_interrupt(ddf_fun_t *fnode, int irq)
+{
+	icp_fun_t *fun = icp_fun(fnode);
+
+	if (!icp_fun_owns_interrupt(fun, irq))
+		return EINVAL;
+
+	return irc_disable_interrupt(irq);
+}
+
+static int icp_fun_clear_interrupt(ddf_fun_t *fnode, int irq)
+{
+	icp_fun_t *fun = icp_fun(fnode);
+
+	if (!icp_fun_owns_interrupt(fun, irq))
+		return EINVAL;
+
+	return irc_clear_interrupt(irq);
 }
 
@@ -155,5 +215,7 @@
 static hw_res_ops_t icp_hw_res_ops = {
 	.get_resource_list = &icp_get_resources,
-	.enable_interrupt = &icp_enable_interrupt,
+	.enable_interrupt = &icp_fun_enable_interrupt,
+	.disable_interrupt = &icp_fun_disable_interrupt,
+	.clear_interrupt = &icp_fun_clear_interrupt
 };
 
@@ -225,4 +287,9 @@
 		return rc;
 
+	rc = icp_add_fun(dev, "intctl", "integratorcp/intctl",
+	    &icp_ic_fun_proto);
+	if (rc != EOK)
+		return rc;
+
 	return EOK;
 }
Index: uspace/drv/platform/mac/mac.c
===================================================================
--- uspace/drv/platform/mac/mac.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/platform/mac/mac.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Martin Decky
+ * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -40,5 +41,7 @@
 #include <errno.h>
 #include <ops/hw_res.h>
+#include <ops/pio_window.h>
 #include <stdio.h>
+#include <sysinfo.h>
 
 #define NAME  "mac"
@@ -46,5 +49,37 @@
 typedef struct {
 	hw_resource_list_t hw_resources;
+	pio_window_t pio_window;
 } mac_fun_t;
+
+static hw_resource_t adb_res[] = {
+	{
+		.type = IO_RANGE,
+		.res.io_range = {
+			.address = 0,
+			.size = 0x2000,
+			.relative = true,
+			.endianness = BIG_ENDIAN
+		}
+	},
+	{
+		.type = INTERRUPT,
+		.res.interrupt = {
+			.irq = 0 /* patched at run time */
+		}
+	},
+};
+
+static mac_fun_t adb_data = {
+	.hw_resources = {
+		sizeof(adb_res) / sizeof(adb_res[0]),
+		adb_res
+	},
+	.pio_window = {
+		.io = {
+			.base = 0, /* patched at run time */
+			.size = 0x2000
+		}
+	}
+};
 
 static hw_resource_t pci_conf_regs[] = {
@@ -79,7 +114,13 @@
 
 /** Obtain function soft-state from DDF function node */
-static mac_fun_t *mac_fun(ddf_fun_t *fnode)
-{
-	return ddf_fun_data_get(fnode);
+static mac_fun_t *mac_fun(ddf_fun_t *ddf_fun)
+{
+	return ddf_fun_data_get(ddf_fun);
+}
+
+static pio_window_t *mac_get_pio_window(ddf_fun_t *ddf_fun)
+{
+	mac_fun_t *fun = mac_fun(ddf_fun);
+	return &fun->pio_window;
 }
 
@@ -88,4 +129,5 @@
 {
 	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
+	printf("mac: Adding new function '%s'.\n", name);
 	
 	ddf_fun_t *fnode = NULL;
@@ -114,4 +156,5 @@
 	}
 	
+	printf("mac: Added new function '%s' (str=%s).\n", name, str_match_id);
 	return true;
 	
@@ -135,13 +178,31 @@
 static int mac_dev_add(ddf_dev_t *dev)
 {
+	int rc;
+	uintptr_t cuda_physical;
+	sysarg_t cuda_inr;
 #if 0
 	/* Register functions */
-	if (!mac_add_fun(dev, "pci0", "intel_pci", &pci_data))
-		ddf_msg(LVL_ERROR, "Failed to add functions for Mac platform.");
+	if (!mac_add_fun(dev, "pci0", "intel_pci", &pci_data)) {
+		ddf_msg(LVL_ERROR, "Failed to add PCI function for Mac platform.");
+		return EIO;
+	}
 #else
 	(void)pci_data;
-	(void)mac_add_fun;
 #endif
-	
+	rc = sysinfo_get_value("cuda.address.physical", &cuda_physical);
+	if (rc != EOK)
+		return EIO;
+	rc = sysinfo_get_value("cuda.inr", &cuda_inr);
+	if (rc != EOK)
+		return EIO;
+
+	adb_data.pio_window.io.base = cuda_physical;
+	adb_res[1].res.interrupt.irq = cuda_inr;
+
+	if (!mac_add_fun(dev, "adb", "cuda_adb", &adb_data)) {
+		ddf_msg(LVL_ERROR, "Failed to add ADB function for Mac platform.");
+		return EIO;
+	}
+
 	return EOK;
 }
@@ -166,5 +227,5 @@
 }
 
-static bool mac_enable_interrupt(ddf_fun_t *fun)
+static int mac_enable_interrupt(ddf_fun_t *fun, int irq)
 {
 	/* TODO */
@@ -172,4 +233,8 @@
 	return false;
 }
+
+static pio_window_ops_t fun_pio_window_ops = {
+        .get_pio_window = &mac_get_pio_window
+};
 
 static hw_res_ops_t fun_hw_res_ops = {
@@ -183,4 +248,5 @@
 	ddf_log_init(NAME);
 	mac_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
+	mac_fun_ops.interfaces[PIO_WINDOW_DEV_IFACE] = &fun_pio_window_ops;
 	return ddf_driver_main(&mac_driver);
 }
Index: uspace/drv/platform/malta/malta.c
===================================================================
--- uspace/drv/platform/malta/malta.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/platform/malta/malta.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -143,5 +143,5 @@
 }
 
-static bool malta_enable_interrupt(ddf_fun_t *fun)
+static int malta_enable_interrupt(ddf_fun_t *fun, int irq)
 {
 	/* TODO */
Index: uspace/drv/platform/msim/msim.c
===================================================================
--- uspace/drv/platform/msim/msim.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/platform/msim/msim.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -121,5 +121,5 @@
 }
 
-static bool msim_enable_interrupt(ddf_fun_t *fun)
+static int msim_enable_interrupt(ddf_fun_t *fun, int irq)
 {
 	/* Nothing to do. */
Index: uspace/drv/platform/pc/pc.c
===================================================================
--- uspace/drv/platform/pc/pc.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/platform/pc/pc.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -125,5 +125,5 @@
 }
 
-static bool pc_enable_interrupt(ddf_fun_t *fun)
+static int pc_enable_interrupt(ddf_fun_t *fun, int irq)
 {
 	/* TODO */
Index: uspace/drv/platform/sun4u/sun4u.c
===================================================================
--- uspace/drv/platform/sun4u/sun4u.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/platform/sun4u/sun4u.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -130,5 +130,5 @@
 }
 
-static bool sun4u_enable_interrupt(ddf_fun_t *fun)
+static int sun4u_enable_interrupt(ddf_fun_t *fun, int irq)
 {
 	/* TODO */
Index: uspace/drv/test/test1/test1.c
===================================================================
--- uspace/drv/test/test1/test1.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/test/test1/test1.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -135,5 +135,5 @@
  * /virtual/test1/clone/child
  *
- * and devman shall not deadlock.
+ * and the DDF shall not deadlock.
  *
  *
Index: uspace/drv/time/cmos-rtc/cmos-rtc.c
===================================================================
--- uspace/drv/time/cmos-rtc/cmos-rtc.c	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
+++ uspace/drv/time/cmos-rtc/cmos-rtc.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
@@ -213,6 +213,6 @@
 	/* Connect to the parent's driver */
 
-	parent_sess = ddf_dev_parent_sess_create(rtc->dev);
-	if (!parent_sess) {
+	parent_sess = ddf_dev_parent_sess_get(rtc->dev);
+	if (parent_sess == NULL) {
 		ddf_msg(LVL_ERROR, "Failed to connect to parent driver\
 		    of device %s.", ddf_dev_get_name(rtc->dev));
