Index: abi/include/ddi/irq.h
===================================================================
--- abi/include/ddi/irq.h	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ abi/include/ddi/irq.h	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -36,4 +36,9 @@
 #define ABI_DDI_IRQ_H_
 
+typedef struct {
+	uintptr_t base;
+	size_t size;
+} irq_pio_range_t;
+
 typedef enum {
 	/** Read 1 byte from the I/O space. */
@@ -67,25 +72,4 @@
 	CMD_PIO_WRITE_A_32,
 	
-	/** Read 1 byte from the memory space. */
-	CMD_MEM_READ_8,
-	/** Read 2 bytes from the memory space. */
-	CMD_MEM_READ_16,
-	/** Read 4 bytes from the memory space. */
-	CMD_MEM_READ_32,
-	
-	/** Write 1 byte to the memory space. */
-	CMD_MEM_WRITE_8,
-	/** Write 2 bytes to the memory space. */
-	CMD_MEM_WRITE_16,
-	/** Write 4 bytes to the memory space. */
-	CMD_MEM_WRITE_32,
-	
-	/** Write 1 byte from the source argument to the memory space. */
-	CMD_MEM_WRITE_A_8,
-	/** Write 2 bytes from the source argument to the memory space. */
-	CMD_MEM_WRITE_A_16,
-	/** Write 4 bytes from the source argument to the memory space. */
-	CMD_MEM_WRITE_A_32,
-	
 	/**
 	 * Perform a bit masking on the source argument
@@ -118,4 +102,6 @@
 
 typedef struct {
+	size_t rangecount;
+	irq_pio_range_t *ranges;
 	size_t cmdcount;
 	irq_cmd_t *cmds;
Index: kernel/arch/arm32/src/mach/integratorcp/integratorcp.c
===================================================================
--- kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -332,8 +332,6 @@
 	sysinfo_set_item_val("kbd", NULL, true);
 	sysinfo_set_item_val("kbd.inr", NULL, ICP_KBD_IRQ);
-	sysinfo_set_item_val("kbd.address.status", NULL,
-	    (uintptr_t) icp_hw_map.kbd_stat);
-	sysinfo_set_item_val("kbd.address.data", NULL,
-	    (uintptr_t) icp_hw_map.kbd_data);
+	sysinfo_set_item_val("kbd.address.physical", NULL,
+	    ICP_KBD);
 
 }
Index: kernel/arch/arm32/src/mach/testarm/testarm.c
===================================================================
--- kernel/arch/arm32/src/mach/testarm/testarm.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ kernel/arch/arm32/src/mach/testarm/testarm.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -128,5 +128,6 @@
 	sysinfo_set_item_val("kbd", NULL, true);
 	sysinfo_set_item_val("kbd.inr", NULL, GXEMUL_KBD_IRQ);
-	sysinfo_set_item_val("kbd.address.virtual", NULL, (sysarg_t) gxemul_kbd);
+	sysinfo_set_item_val("kbd.address.physical", NULL,
+	    GXEMUL_KBD_ADDRESS);
 #endif
 }
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ kernel/arch/ia64/src/ia64.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -188,6 +188,4 @@
 	sysinfo_set_item_val("kbd.address.physical", NULL,
 	    (uintptr_t) NS16550_BASE);
-	sysinfo_set_item_val("kbd.address.kernel", NULL,
-	    (uintptr_t) NS16550_BASE);
 #endif
 	
Index: kernel/arch/mips32/src/mips32.c
===================================================================
--- kernel/arch/mips32/src/mips32.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ kernel/arch/mips32/src/mips32.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -196,5 +196,6 @@
 	sysinfo_set_item_val("kbd", NULL, true);
 	sysinfo_set_item_val("kbd.inr", NULL, MSIM_KBD_IRQ);
-	sysinfo_set_item_val("kbd.address.virtual", NULL, MSIM_KBD_ADDRESS);
+	sysinfo_set_item_val("kbd.address.physical", NULL,
+	    PA2KA(MSIM_KBD_ADDRESS));
 #endif
 }
Index: kernel/arch/ppc32/src/ppc32.c
===================================================================
--- kernel/arch/ppc32/src/ppc32.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ kernel/arch/ppc32/src/ppc32.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -232,6 +232,4 @@
 		sysinfo_set_item_val("cuda.inr", NULL, IRQ_CUDA);
 		sysinfo_set_item_val("cuda.address.physical", NULL, pa);
-		sysinfo_set_item_val("cuda.address.kernel", NULL,
-		    (uintptr_t) cuda);
 #endif
 	}
Index: kernel/arch/sparc64/src/drivers/kbd.c
===================================================================
--- kernel/arch/sparc64/src/drivers/kbd.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ kernel/arch/sparc64/src/drivers/kbd.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -133,6 +133,4 @@
 	sysinfo_set_item_val("kbd", NULL, true);
 	sysinfo_set_item_val("kbd.inr", NULL, inr);
-	sysinfo_set_item_val("kbd.address.kernel", NULL,
-	    (uintptr_t) ns16550);
 	sysinfo_set_item_val("kbd.address.physical", NULL, pa);
 	sysinfo_set_item_val("kbd.type.ns16550", NULL, true);
Index: kernel/generic/include/ddi/irq.h
===================================================================
--- kernel/generic/include/ddi/irq.h	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ kernel/generic/include/ddi/irq.h	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -134,6 +134,4 @@
 	/** Notification configuration structure. */
 	ipc_notif_cfg_t notif_cfg; 
-	
-	as_t *driver_as;
 } irq_t;
 
Index: kernel/generic/include/ipc/irq.h
===================================================================
--- kernel/generic/include/ipc/irq.h	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ kernel/generic/include/ipc/irq.h	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -36,5 +36,8 @@
 #define KERN_IPC_IRQ_H_
 
-/** Maximum length of IPC IRQ program */
+/** Maximum number of IPC IRQ programmed I/O ranges. */
+#define IRQ_MAX_RANGE_COUNT	8
+
+/** Maximum length of IPC IRQ program. */
 #define IRQ_MAX_PROG_SIZE  20
 
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ kernel/generic/src/ipc/irq.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -74,4 +74,6 @@
 #include <arch.h>
 #include <mm/slab.h>
+#include <mm/page.h>
+#include <mm/km.h>
 #include <errno.h>
 #include <ddi/irq.h>
@@ -81,4 +83,101 @@
 #include <console/console.h>
 #include <print.h>
+#include <macros.h>
+
+static void ranges_unmap(irq_pio_range_t *ranges, size_t rangecount)
+{
+	size_t i;
+
+	for (i = 0; i < rangecount; i++) {
+#ifdef IO_SPACE_BOUNDARY
+		if ((void *) ranges[i].base >= IO_SPACE_BOUNDARY)
+#endif
+			km_unmap(ranges[i].base, ranges[i].size);
+	}
+}
+
+static int ranges_map_and_apply(irq_pio_range_t *ranges, size_t rangecount,
+    irq_cmd_t *cmds, size_t cmdcount)
+{
+	uintptr_t *pbase;
+	size_t i, j;
+
+	/* Copy the physical base addresses aside. */
+	pbase = malloc(rangecount * sizeof(uintptr_t), 0);
+	for (i = 0; i < rangecount; i++)
+		pbase[i] = ranges[i].base;
+
+	/* Map the PIO ranges into the kernel virtual address space. */
+	for (i = 0; i < rangecount; i++) {
+#ifdef IO_SPACE_BOUNDARY
+		if ((void *) ranges[i].base < IO_SPACE_BOUNDARY)
+			continue;
+#endif
+		ranges[i].base = km_map(pbase[i], ranges[i].size,
+		    PAGE_READ | PAGE_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
+		if (!ranges[i].base) {
+			ranges_unmap(ranges, i);
+			free(pbase);
+			return ENOMEM;
+		}
+	}
+
+	/* Rewrite the pseudocode addresses from physical to kernel virtual. */
+	for (i = 0; i < cmdcount; i++) {
+		uintptr_t addr;
+		size_t size;
+
+		/* Process only commands that use an address. */
+		switch (cmds[i].cmd) {
+		case CMD_PIO_READ_8:
+        	case CMD_PIO_WRITE_8:
+        	case CMD_PIO_WRITE_A_8:
+			size = 1;
+			break;
+        	case CMD_PIO_READ_16:
+        	case CMD_PIO_WRITE_16:
+        	case CMD_PIO_WRITE_A_16:
+			size = 2;
+			break;
+        	case CMD_PIO_READ_32:
+        	case CMD_PIO_WRITE_32:
+        	case CMD_PIO_WRITE_A_32:
+			size = 4;
+			break;
+		default:
+			/* Move onto the next command. */
+			continue;
+		}
+
+		addr = (uintptr_t) cmds[i].addr;
+		
+		for (j = 0; j < rangecount; j++) {
+
+			/* Find the matching range. */
+			if (!iswithin(pbase[j], ranges[j].size, addr, size))
+				continue;
+
+			/* Switch the command to a kernel virtual address. */
+			addr -= pbase[j];
+			addr += ranges[j].base;
+
+			cmds[i].addr = (void *) addr;
+			break;
+		}
+
+		if (j == rangecount) {
+			/*
+			 * The address used in this command is outside of all
+			 * defined ranges.
+			 */
+			ranges_unmap(ranges, rangecount);
+			free(pbase);
+			return EINVAL;
+		}
+	}
+
+	free(pbase);
+	return EOK;
+}
 
 /** Free the top-half pseudocode.
@@ -90,4 +189,6 @@
 {
 	if (code) {
+		ranges_unmap(code->ranges, code->rangecount);
+		free(code->ranges);
 		free(code->cmds);
 		free(code);
@@ -104,27 +205,45 @@
 static irq_code_t *code_from_uspace(irq_code_t *ucode)
 {
+	irq_pio_range_t *ranges = NULL;
+	irq_cmd_t *cmds = NULL;
+
 	irq_code_t *code = malloc(sizeof(*code), 0);
 	int rc = copy_from_uspace(code, ucode, sizeof(*code));
-	if (rc != 0) {
-		free(code);
-		return NULL;
-	}
-	
-	if (code->cmdcount > IRQ_MAX_PROG_SIZE) {
-		free(code);
-		return NULL;
-	}
-	
-	irq_cmd_t *ucmds = code->cmds;
-	code->cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0);
-	rc = copy_from_uspace(code->cmds, ucmds,
+	if (rc != EOK)
+		goto error;
+	
+	if ((code->rangecount > IRQ_MAX_RANGE_COUNT) ||
+	    (code->cmdcount > IRQ_MAX_PROG_SIZE))
+		goto error;
+	
+	ranges = malloc(sizeof(code->ranges[0]) * code->rangecount, 0);
+	rc = copy_from_uspace(ranges, code->ranges,
+	    sizeof(code->ranges[0]) * code->rangecount);
+	if (rc != EOK)
+		goto error;
+
+	cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0);
+	rc = copy_from_uspace(cmds, code->cmds,
 	    sizeof(code->cmds[0]) * code->cmdcount);
-	if (rc != 0) {
-		free(code->cmds);
-		free(code);
-		return NULL;
-	}
-	
+	if (rc != EOK)
+		goto error;
+
+	rc = ranges_map_and_apply(ranges, code->rangecount, cmds,
+	    code->cmdcount);
+	if (rc != EOK)
+		goto error;
+
+	code->ranges = ranges;
+	code->cmds = cmds;
+
 	return code;
+
+error:
+	if (cmds)
+		free(cmds);
+	if (ranges)
+		free(ranges);
+	free(code);
+	return NULL;
 }
 
@@ -174,5 +293,4 @@
 	irq->notif_cfg.code = code;
 	irq->notif_cfg.counter = 0;
-	irq->driver_as = AS;
 	
 	/*
@@ -365,14 +483,6 @@
 		return IRQ_DECLINE;
 	
-	as_t *current_as = AS;
-	if (current_as != irq->driver_as)
-		as_switch(AS, irq->driver_as);
-	
 	for (size_t i = 0; i < code->cmdcount; i++) {
 		uint32_t dstval;
-		void *va;
-		uint8_t val8;
-		uint16_t val16;
-		uint32_t val32;
 		
 		uintptr_t srcarg = code->cmds[i].srcarg;
@@ -431,58 +541,4 @@
 			}
 			break;
-		case CMD_MEM_READ_8:
-			va = code->cmds[i].addr;
-			memcpy_from_uspace(&val8, va, sizeof(val8));
-			if (dstarg)
-				scratch[dstarg] = val8;
-			break;
-		case CMD_MEM_READ_16:
-			va = code->cmds[i].addr;
-			memcpy_from_uspace(&val16, va, sizeof(val16));
-			if (dstarg)
-				scratch[dstarg] = val16;
-			break;
-		case CMD_MEM_READ_32:
-			va = code->cmds[i].addr;
-			memcpy_from_uspace(&val32, va, sizeof(val32));
-			if (dstarg)
-				scratch[dstarg] = val32;
-			break;
-		case CMD_MEM_WRITE_8:
-			val8 = code->cmds[i].value;
-			va = code->cmds[i].addr;
-			memcpy_to_uspace(va, &val8, sizeof(val8));
-			break;
-		case CMD_MEM_WRITE_16:
-			val16 = code->cmds[i].value;
-			va = code->cmds[i].addr;
-			memcpy_to_uspace(va, &val16, sizeof(val16));
-			break;
-		case CMD_MEM_WRITE_32:
-			val32 = code->cmds[i].value;
-			va = code->cmds[i].addr;
-			memcpy_to_uspace(va, &val32, sizeof(val32));
-			break;
-		case CMD_MEM_WRITE_A_8:
-			if (srcarg) {
-				val8 = scratch[srcarg];
-				va = code->cmds[i].addr;
-				memcpy_to_uspace(va, &val8, sizeof(val8));
-			}
-			break;
-		case CMD_MEM_WRITE_A_16:
-			if (srcarg) {
-				val16 = scratch[srcarg];
-				va = code->cmds[i].addr;
-				memcpy_to_uspace(va, &val16, sizeof(val16));
-			}
-			break;
-		case CMD_MEM_WRITE_A_32:
-			if (srcarg) {
-				val32 = scratch[srcarg];
-				va = code->cmds[i].addr;
-				memcpy_to_uspace(va, &val32, sizeof(val32));
-			}
-			break;
 		case CMD_BTEST:
 			if ((srcarg) && (dstarg)) {
@@ -498,17 +554,10 @@
 			break;
 		case CMD_ACCEPT:
-			if (AS != current_as)
-				as_switch(AS, current_as);
 			return IRQ_ACCEPT;
 		case CMD_DECLINE:
 		default:
-			if (AS != current_as)
-				as_switch(AS, current_as);
 			return IRQ_DECLINE;
 		}
 	}
-	
-	if (AS != current_as)
-		as_switch(AS, current_as);
 	
 	return IRQ_DECLINE;
Index: kernel/generic/src/main/main.c
===================================================================
--- kernel/generic/src/main/main.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ kernel/generic/src/main/main.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -257,5 +257,5 @@
 		for (i = 0; i < init.cnt; i++)
 			LOG("init[%zu].addr=%p, init[%zu].size=%zu",
-			    i, (void *) init.tasks[i].addr, i, init.tasks[i].size);
+			    i, (void *) init.tasks[i].paddr, i, init.tasks[i].size);
 	} else
 		printf("No init binaries found.\n");
Index: kernel/generic/src/syscall/copy.c
===================================================================
--- kernel/generic/src/syscall/copy.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ kernel/generic/src/syscall/copy.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -56,5 +56,5 @@
  * @param size Size of the data to be copied.
  *
- * @return 0 on success or error code from @ref errno.h.
+ * @return EOK on success or error code from @ref errno.h.
  */
 int copy_from_uspace(void *dst, const void *uspace_src, size_t size)
@@ -94,5 +94,5 @@
 
 	interrupts_restore(ipl);
-	return !rc ? EPERM : 0;
+	return !rc ? EPERM : EOK;
 }
 
Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -47,10 +47,16 @@
     (I_SO | I_WDH | I_UE | I_RHSC)
 
-static const irq_cmd_t ohci_irq_commands[] =
-{
-	{ .cmd = CMD_MEM_READ_32, .dstarg = 1, .addr = NULL /*filled later*/ },
+static const irq_pio_range_t ohci_pio_ranges[] = {
+	{
+		.base = 0,	/* filled later */
+		.size = sizeof(ohci_regs_t)
+	}
+};
+
+static const irq_cmd_t ohci_irq_commands[] = {
+	{ .cmd = CMD_PIO_READ_32, .dstarg = 1, .addr = NULL /* filled later */ },
 	{ .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = OHCI_USED_INTERRUPTS },
 	{ .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
-	{ .cmd = CMD_MEM_WRITE_A_32, .srcarg = 1, .addr = NULL /*filled later*/ },
+	{ .cmd = CMD_PIO_WRITE_A_32, .srcarg = 1, .addr = NULL /* filled later */ },
 	{ .cmd = CMD_ACCEPT },
 };
@@ -63,4 +69,13 @@
 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
 /*----------------------------------------------------------------------------*/
+/** Get number of PIO ranges used in IRQ code.
+ * @return Number of ranges.
+ */
+size_t hc_irq_pio_range_count(void)
+{
+	return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);
+}
+/*----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
 /** Get number of commands used in IRQ code.
  * @return Number of commands.
@@ -71,7 +86,9 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Generate IRQ code commands.
- * @param[out] cmds Place to store the commands.
- * @param[in] cmd_size Size of the place (bytes).
+/** Generate IRQ code.
+ * @param[out] ranges PIO ranges buffer.
+ * @param[in] ranges_size Size of the ranges buffer (bytes).
+ * @param[out] cmds Commands buffer.
+ * @param[in] cmds_size Size of the commands buffer (bytes).
  * @param[in] regs Physical address of device's registers.
  * @param[in] reg_size Size of the register area (bytes).
@@ -79,38 +96,21 @@
  * @return Error code.
  */
-int hc_get_irq_commands(
-    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
-{
-	if (cmd_size < sizeof(ohci_irq_commands)
-	    || reg_size < sizeof(ohci_regs_t))
+int
+hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[],
+    size_t cmds_size, uintptr_t regs, size_t reg_size)
+{
+	if ((ranges_size < sizeof(ohci_pio_ranges)) ||
+	    (cmds_size < sizeof(ohci_irq_commands)) ||
+	    (reg_size < sizeof(ohci_regs_t)))
 		return EOVERFLOW;
 
-	/* Create register mapping to use in IRQ handler.
-	 * This mapping should be present in kernel only.
-	 * Remove it from here when kernel knows how to create mappings
-	 * and accepts physical addresses in IRQ code.
-	 * TODO: remove */
-	ohci_regs_t *registers;
-	const int ret = pio_enable((void*)regs, reg_size, (void**)&registers);
-	if (ret != EOK)
-		return ret;
-
-	/* Some bogus access to force create mapping. DO NOT remove,
-	 * unless whole virtual addresses in irq is replaced
-	 * NOTE: Compiler won't remove this as ohci_regs_t members
-	 * are declared volatile.
-	 *
-	 * Introducing CMD_MEM set of IRQ code commands broke
-	 * assumption that IRQ code does not cause page faults.
-	 * If this happens during idling (THREAD == NULL)
-	 * it causes kernel panic.
-	 */
-	registers->revision;
+	memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges));
+	ranges[0].base = regs;
 
 	memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
-
-	void *address = (void*)&registers->interrupt_status;
-	cmds[0].addr = address;
-	cmds[3].addr = address;
+	ohci_regs_t *registers = (ohci_regs_t *) regs;
+	cmds[0].addr = (void *) &registers->interrupt_status;
+	cmds[3].addr = (void *) &registers->interrupt_status;
+
 	return EOK;
 }
Index: uspace/drv/bus/usb/ohci/hc.h
===================================================================
--- uspace/drv/bus/usb/ohci/hc.h	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/drv/bus/usb/ohci/hc.h	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -74,7 +74,8 @@
 } hc_t;
 
+size_t hc_irq_pio_range_count(void);
 size_t hc_irq_cmd_count(void);
-int hc_get_irq_commands(
-    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
+int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, uintptr_t,
+    size_t);
 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
 int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
Index: uspace/drv/bus/usb/ohci/ohci.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -187,12 +187,19 @@
 	    (void *) reg_base, reg_size, irq);
 
-	const size_t cmd_count = hc_irq_cmd_count();
-	irq_cmd_t irq_cmds[cmd_count];
-	irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
-
-	ret =
-	    hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
-	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed to generate IRQ commands: %s.\n", str_error(ret));
+	const size_t ranges_count = hc_irq_pio_range_count();
+	const size_t cmds_count = hc_irq_cmd_count();
+	irq_pio_range_t irq_ranges[ranges_count];
+	irq_cmd_t irq_cmds[cmds_count];
+	irq_code_t irq_code = {
+		.rangecount = ranges_count,
+		.ranges = irq_ranges,
+		.cmdcount = cmds_count,
+		.cmds = irq_cmds
+	};
+
+	ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
+	    sizeof(irq_cmds), reg_base, reg_size);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to generate IRQ code: %s.\n", str_error(ret));
 
 
Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -48,7 +48,12 @@
     (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
 
-
-static const irq_cmd_t uhci_irq_commands[] =
-{
+static const irq_pio_range_t uhci_irq_pio_ranges[] = {
+	{
+		.base = 0,	/* filled later */
+		.size = sizeof(uhci_regs_t)
+	}
+};
+
+static const irq_cmd_t uhci_irq_commands[] = {
 	{ .cmd = CMD_PIO_READ_16, .dstarg = 1, .addr = NULL/*filled later*/},
 	{ .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2,
@@ -68,4 +73,12 @@
 
 /*----------------------------------------------------------------------------*/
+/** Get number of PIO ranges used in IRQ code.
+ * @return Number of ranges.
+ */
+size_t hc_irq_pio_range_count(void)
+{
+	return sizeof(uhci_irq_pio_ranges) / sizeof(irq_pio_range_t);
+}
+/*----------------------------------------------------------------------------*/
 /** Get number of commands used in IRQ code.
  * @return Number of commands.
@@ -76,7 +89,9 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Generate IRQ code commands.
- * @param[out] cmds Place to store the commands.
- * @param[in] cmd_size Size of the place (bytes).
+/** Generate IRQ code.
+ * @param[out] ranges PIO ranges buffer.
+ * @param[in] ranges_size Size of the ranges buffer (bytes).
+ * @param[out] cmds Commands buffer.
+ * @param[in] cmds_size Size of the commands buffer (bytes).
  * @param[in] regs Physical address of device's registers.
  * @param[in] reg_size Size of the register area (bytes).
@@ -84,17 +99,21 @@
  * @return Error code.
  */
-int hc_get_irq_commands(
-    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
-{
-	if (cmd_size < sizeof(uhci_irq_commands)
-	    || reg_size < sizeof(uhci_regs_t))
+int
+hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[],
+    size_t cmds_size, uintptr_t regs, size_t reg_size)
+{
+	if ((ranges_size < sizeof(uhci_irq_pio_ranges)) ||
+	    (cmds_size < sizeof(uhci_irq_commands)) ||
+	    (reg_size < sizeof(uhci_regs_t)))
 		return EOVERFLOW;
 
-	uhci_regs_t *registers = (uhci_regs_t*)regs;
+	memcpy(ranges, uhci_irq_pio_ranges, sizeof(uhci_irq_pio_ranges));
+	ranges[0].base = regs;
 
 	memcpy(cmds, uhci_irq_commands, sizeof(uhci_irq_commands));
-
-	cmds[0].addr = (void*)&registers->usbsts;
-	cmds[3].addr = (void*)&registers->usbsts;
+	uhci_regs_t *registers = (uhci_regs_t *) regs;
+	cmds[0].addr = &registers->usbsts;
+	cmds[3].addr = &registers->usbsts;
+
 	return EOK;
 }
Index: uspace/drv/bus/usb/uhci/hc.h
===================================================================
--- uspace/drv/bus/usb/uhci/hc.h	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/drv/bus/usb/uhci/hc.h	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -121,7 +121,8 @@
 } hc_t;
 
+size_t hc_irq_pio_range_count(void);
 size_t hc_irq_cmd_count(void);
-int hc_get_irq_commands(
-    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
+int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, uintptr_t,
+    size_t);
 void hc_interrupt(hc_t *instance, uint16_t status);
 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
Index: uspace/drv/bus/usb/uhci/uhci.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/drv/bus/usb/uhci/uhci.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -198,12 +198,19 @@
 	    "Failed to disable legacy USB: %s.\n", str_error(ret));
 
-	const size_t cmd_count = hc_irq_cmd_count();
-	irq_cmd_t irq_cmds[cmd_count];
-	ret =
-	    hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
+	const size_t ranges_count = hc_irq_pio_range_count();
+	const size_t cmds_count = hc_irq_cmd_count();
+	irq_pio_range_t irq_ranges[ranges_count];
+	irq_cmd_t irq_cmds[cmds_count];
+	ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
+	    sizeof(irq_cmds), reg_base, reg_size);
 	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed to generate IRQ commands: %s.\n", str_error(ret));
 
-	irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
+	irq_code_t irq_code = {
+		.rangecount = ranges_count,
+		.ranges = irq_ranges,
+		.cmdcount = cmds_count,
+		.cmds = irq_cmds
+	};
 
         /* Register handler to avoid interrupt lockup */
Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/drv/char/i8042/i8042.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -105,4 +105,11 @@
 };
 
+static const irq_pio_range_t i8042_ranges[] = {
+	{
+		.base = 0,
+		.size = sizeof(i8042_regs_t)
+	}
+};
+
 /** i8042 Interrupt pseudo-code. */
 static const irq_cmd_t i8042_cmds[] = {
@@ -239,12 +246,20 @@
 	while (pio_read_8(&dev->regs->status) & i8042_OUTPUT_FULL)
 		(void) pio_read_8(&dev->regs->data);
-	
+
+	const size_t range_count = sizeof(i8042_ranges) /
+	    sizeof(irq_pio_range_t);
+	irq_pio_range_t ranges[range_count];
+	memcpy(ranges, i8042_ranges, sizeof(i8042_ranges));
+	ranges[0].base = (uintptr_t) regs;
+
 	const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
 	irq_cmd_t cmds[cmd_count];
 	memcpy(cmds, i8042_cmds, sizeof(i8042_cmds));
-	cmds[0].addr = (void *) &dev->regs->status;
-	cmds[3].addr = (void *) &dev->regs->data;
-	
+	cmds[0].addr = (void *) &(((i8042_regs_t *) regs)->status);
+	cmds[3].addr = (void *) &(((i8042_regs_t *) regs)->data);
+
 	irq_code_t irq_code = {
+		.rangecount = range_count,
+		.ranges = ranges,
 		.cmdcount = cmd_count,
 		.cmds = cmds
Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/drv/nic/e1k/e1k.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -228,4 +228,12 @@
 static void e1000_send_frame(nic_t *, void *, size_t);
 
+/** PIO ranges used in the IRQ code. */
+irq_pio_range_t e1000_irq_pio_ranges[] = {
+	{
+		.base = 0,
+		.size =	PAGE_SIZE,	/* XXX */
+	}
+};
+
 /** Commands to deal with interrupt
  *
@@ -256,4 +264,7 @@
 /** Interrupt code definition */
 irq_code_t e1000_irq_code = {
+	.rangecount = sizeof(e1000_irq_pio_ranges) /
+	    sizeof(irq_pio_range_t),
+	.ranges = e1000_irq_pio_ranges,
 	.cmdcount = sizeof(e1000_irq_commands) / sizeof(irq_cmd_t),
 	.cmds = e1000_irq_commands
@@ -1252,6 +1263,7 @@
 	fibril_mutex_lock(&irq_reg_mutex);
 	
-	e1000_irq_code.cmds[0].addr = e1000->reg_base_virt + E1000_ICR;
-	e1000_irq_code.cmds[2].addr = e1000->reg_base_virt + E1000_IMC;
+	e1000_irq_code.ranges[0].base = (uintptr_t) e1000->reg_base_phys;
+	e1000_irq_code.cmds[0].addr = e1000->reg_base_phys + E1000_ICR;
+	e1000_irq_code.cmds[2].addr = e1000->reg_base_phys + E1000_IMC;
 	
 	int rc = register_interrupt_handler(nic_get_ddf_dev(nic),
Index: uspace/drv/nic/ne2k/ne2k.c
===================================================================
--- uspace/drv/nic/ne2k/ne2k.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -64,4 +64,11 @@
 #define NE2K(device) ((ne2k_t *) nic_get_specific(DRIVER_DATA(device)))
 
+static irq_pio_range_t ne2k_ranges_prototype[] = {
+	{
+		.base = 0,
+		.size = NE2K_IO_SIZE, 
+	}
+};
+
 /** NE2000 kernel interrupt command sequence.
  *
@@ -122,15 +129,32 @@
 
 	if (ne2k->code.cmdcount == 0) {
-		irq_cmd_t *ne2k_cmds = malloc(sizeof(ne2k_cmds_prototype));
-		if (ne2k_cmds == NULL) {
+		irq_pio_range_t *ne2k_ranges;
+		irq_cmd_t *ne2k_cmds;
+
+		ne2k_ranges = malloc(sizeof(ne2k_ranges_prototype));
+		if (!ne2k_ranges)
+			return ENOMEM;
+		memcpy(ne2k_ranges, ne2k_ranges_prototype,
+		    sizeof(ne2k_ranges_prototype));
+		ne2k_ranges[0].base = (uintptr_t) ne2k->base_port;
+
+		ne2k_cmds = malloc(sizeof(ne2k_cmds_prototype));
+		if (!ne2k_cmds) {
+			free(ne2k_ranges);
 			return ENOMEM;
 		}
-		memcpy(ne2k_cmds, ne2k_cmds_prototype, sizeof (ne2k_cmds_prototype));
-		ne2k_cmds[0].addr = ne2k->port + DP_ISR;
-		ne2k_cmds[3].addr = ne2k->port + DP_IMR;
+		memcpy(ne2k_cmds, ne2k_cmds_prototype,
+		    sizeof(ne2k_cmds_prototype));
+		ne2k_cmds[0].addr = ne2k->base_port + DP_ISR;
+		ne2k_cmds[3].addr = ne2k->base_port + DP_IMR;
 		ne2k_cmds[4].addr = ne2k_cmds[0].addr;
-		ne2k_cmds[5].addr = ne2k->port + DP_TSR;
-
-		ne2k->code.cmdcount = sizeof(ne2k_cmds_prototype) / sizeof(irq_cmd_t);
+		ne2k_cmds[5].addr = ne2k->base_port + DP_TSR;
+
+		ne2k->code.rangecount = sizeof(ne2k_ranges_prototype) /
+		    sizeof(irq_pio_range_t);
+		ne2k->code.ranges = ne2k_ranges;
+
+		ne2k->code.cmdcount = sizeof(ne2k_cmds_prototype) /
+		    sizeof(irq_cmd_t);
 		ne2k->code.cmds = ne2k_cmds;
 	}
@@ -148,4 +172,5 @@
 		ne2k_t *ne2k = NE2K(dev);
 		if (ne2k) {
+			free(ne2k->code.ranges);
 			free(ne2k->code.cmds);
 		}
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/drv/nic/rtl8139/driver.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -661,4 +661,10 @@
 
 
+irq_pio_range_t rtl8139_irq_pio_ranges[] = {
+	{
+		.base = 0,
+		.size = RTL8139_IO_SIZE
+	}
+};
 
 /** Commands to deal with interrupt
@@ -670,35 +676,37 @@
  */
 irq_cmd_t rtl8139_irq_commands[] = {
-		{
-				/* Get the interrupt status */
-				.cmd = CMD_PIO_READ_16,
-				.addr = NULL,
-				.dstarg = 2
-		},
-		{
-				.cmd = CMD_PREDICATE,
-				.value = 3,
-				.srcarg = 2
-		},
-		{
-				/* Mark interrupts as solved */
-				.cmd = CMD_PIO_WRITE_16,
-				.addr = NULL,
-				.value = 0xFFFF
-		},
-		{
-				/* Disable interrupts until interrupt routine is finished */
-				.cmd = CMD_PIO_WRITE_16,
-				.addr = NULL,
-				.value = 0x0000
-		},
-		{
-				.cmd = CMD_ACCEPT
-		}
+	{
+		/* Get the interrupt status */
+		.cmd = CMD_PIO_READ_16,
+		.addr = NULL,
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 3,
+		.srcarg = 2
+	},
+	{
+		/* Mark interrupts as solved */
+		.cmd = CMD_PIO_WRITE_16,
+		.addr = NULL,
+		.value = 0xFFFF
+	},
+	{
+		/* Disable interrupts until interrupt routine is finished */
+		.cmd = CMD_PIO_WRITE_16,
+		.addr = NULL,
+		.value = 0x0000
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
 };
 
 /** Interrupt code definition */
 irq_code_t rtl8139_irq_code = {
-	.cmdcount = sizeof(rtl8139_irq_commands)/sizeof(irq_cmd_t),
+	.rangecount = sizeof(rtl8139_irq_pio_ranges) / sizeof(irq_pio_range_t),
+	.ranges = rtl8139_irq_pio_ranges,
+	.cmdcount = sizeof(rtl8139_irq_commands) / sizeof(irq_cmd_t),
 	.cmds = rtl8139_irq_commands
 };
@@ -890,9 +898,10 @@
 	RTL8139_IRQ_STRUCT_LOCK();
 
-	rtl8139_irq_code.cmds[0].addr = rtl8139->io_port + ISR;
-	rtl8139_irq_code.cmds[2].addr = rtl8139->io_port + ISR;
-	rtl8139_irq_code.cmds[3].addr = rtl8139->io_port + IMR;
+	rtl8139_irq_code.ranges[0].base = (uintptr_t) rtl8139->io_addr;
+	rtl8139_irq_code.cmds[0].addr = rtl8139->io_addr + ISR;
+	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),
-		rtl8139->irq, rtl8139_interrupt_handler, &rtl8139_irq_code);
+	    rtl8139->irq, rtl8139_interrupt_handler, &rtl8139_irq_code);
 
 	RTL8139_IRQ_STRUCT_UNLOCK();
Index: uspace/lib/drv/generic/interrupt.c
===================================================================
--- uspace/lib/drv/generic/interrupt.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/lib/drv/generic/interrupt.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -68,4 +68,6 @@
 
 static irq_code_t default_pseudocode = {
+	0,
+	NULL,
 	sizeof(default_cmds) / sizeof(irq_cmd_t),
 	default_cmds
Index: uspace/srv/hid/input/port/gxemul.c
===================================================================
--- uspace/srv/hid/input/port/gxemul.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/srv/hid/input/port/gxemul.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -57,4 +57,11 @@
 static kbd_dev_t *kbd_dev;
 
+static irq_pio_range_t gxemul_ranges[] = {
+	{
+		.base = 0,
+		.size = 1
+	}
+};
+
 static irq_cmd_t gxemul_cmds[] = {
 	{ 
@@ -69,4 +76,6 @@
 
 static irq_code_t gxemul_kbd = {
+	sizeof(gxemul_ranges) / sizeof(irq_pio_range_t),
+	gxemul_ranges,
 	sizeof(gxemul_cmds) / sizeof(irq_cmd_t),
 	gxemul_cmds
@@ -81,5 +90,5 @@
 	
 	sysarg_t addr;
-	if (sysinfo_get_value("kbd.address.virtual", &addr) != EOK)
+	if (sysinfo_get_value("kbd.address.physical", &addr) != EOK)
 		return -1;
 	
@@ -89,4 +98,5 @@
 	
 	async_set_interrupt_received(gxemul_irq_handler);
+	gxemul_ranges[0].base = addr;
 	gxemul_cmds[0].addr = (void *) addr;
 	irq_register(inr, device_assign_devno(), 0, &gxemul_kbd);
Index: uspace/srv/hid/input/port/msim.c
===================================================================
--- uspace/srv/hid/input/port/msim.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/srv/hid/input/port/msim.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -57,4 +57,11 @@
 static kbd_dev_t *kbd_dev;
 
+static irq_pio_range_t msim_ranges[] = {
+	{
+		.base = 0,
+		.size = 1
+	}
+};
+
 static irq_cmd_t msim_cmds[] = {
 	{
@@ -69,4 +76,6 @@
 
 static irq_code_t msim_kbd = {
+	sizeof(msim_ranges) / sizeof(irq_pio_range_t),
+	msim_ranges,
 	sizeof(msim_cmds) / sizeof(irq_cmd_t),
 	msim_cmds
@@ -79,6 +88,6 @@
 	kbd_dev = kdev;
 
-	sysarg_t vaddr;
-	if (sysinfo_get_value("kbd.address.virtual", &vaddr) != EOK)
+	sysarg_t paddr;
+	if (sysinfo_get_value("kbd.address.physical", &paddr) != EOK)
 		return -1;
 	
@@ -87,5 +96,6 @@
 		return -1;
 	
-	msim_cmds[0].addr = (void *) vaddr;
+	msim_ranges[0].base = paddr;
+	msim_cmds[0].addr = (void *) paddr;
 	async_set_interrupt_received(msim_irq_handler);
 	irq_register(inr, device_assign_devno(), 0, &msim_kbd);
Index: uspace/srv/hid/input/port/ns16550.c
===================================================================
--- uspace/srv/hid/input/port/ns16550.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/srv/hid/input/port/ns16550.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -70,4 +70,11 @@
 #define LSR_DATA_READY  0x01
 
+static irq_pio_range_t ns16550_ranges[] = {
+	{
+		.base = 0,
+		.size = 8
+	}
+};
+
 static irq_cmd_t ns16550_cmds[] = {
 	{
@@ -98,4 +105,6 @@
 
 irq_code_t ns16550_kbd = {
+	sizeof(ns16550_ranges) / sizeof(irq_pio_range_t),
+	ns16550_ranges,
 	sizeof(ns16550_cmds) / sizeof(irq_cmd_t),
 	ns16550_cmds
@@ -105,5 +114,4 @@
 
 static uintptr_t ns16550_physical;
-static uintptr_t ns16550_kernel;
 
 static kbd_dev_t *kbd_dev;
@@ -124,13 +132,11 @@
 		return -1;
 	
-	if (sysinfo_get_value("kbd.address.kernel", &ns16550_kernel) != EOK)
-		return -1;
-	
 	sysarg_t inr;
 	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
 		return -1;
 	
-	ns16550_kbd.cmds[0].addr = (void *) (ns16550_kernel + LSR_REG);
-	ns16550_kbd.cmds[3].addr = (void *) (ns16550_kernel + RBR_REG);
+	ns16550_kbd.ranges[0].base = ns16550_physical;
+	ns16550_kbd.cmds[0].addr = (void *) (ns16550_physical + LSR_REG);
+	ns16550_kbd.cmds[3].addr = (void *) (ns16550_physical + RBR_REG);
 	
 	async_set_interrupt_received(ns16550_irq_handler);
Index: uspace/srv/hid/input/port/pl050.c
===================================================================
--- uspace/srv/hid/input/port/pl050.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/srv/hid/input/port/pl050.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -61,5 +61,15 @@
 static kbd_dev_t *kbd_dev;
 
+#define PL050_STAT	4
+#define PL050_DATA	8
+
 #define PL050_STAT_RXFULL  (1 << 4)
+
+static irq_pio_range_t pl050_ranges[] = {
+	{
+		.base = 0,
+		.size = 9, 
+	}
+};
 
 static irq_cmd_t pl050_cmds[] = {
@@ -91,4 +101,6 @@
 
 static irq_code_t pl050_kbd = {
+	sizeof(pl050_ranges) / sizeof(irq_pio_range_t),
+	pl050_ranges,
 	sizeof(pl050_cmds) / sizeof(irq_cmd_t),
 	pl050_cmds
@@ -102,13 +114,10 @@
 	
 	sysarg_t addr;
-	if (sysinfo_get_value("kbd.address.status", &addr) != EOK)
+	if (sysinfo_get_value("kbd.address.physical", &addr) != EOK)
 		return -1;
 	
-	pl050_kbd.cmds[0].addr = (void *) addr;
-	
-	if (sysinfo_get_value("kbd.address.data", &addr) != EOK)
-		return -1;
-	
-	pl050_kbd.cmds[3].addr = (void *) addr;
+	pl050_kbd.ranges[0].base = addr;
+	pl050_kbd.cmds[0].addr = (void *) addr + PL050_STAT;
+	pl050_kbd.cmds[3].addr = (void *) addr + PL050_DATA;
 	
 	sysarg_t inr;
Index: uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c
===================================================================
--- uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -62,4 +62,6 @@
 
 static irq_code_t ts_irq_code = {
+	0,
+	NULL,
 	sizeof(ts_irq_cmds) / sizeof(irq_cmd_t),
 	ts_irq_cmds
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.c
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -104,4 +104,11 @@
 enum {
 	ADB_MAX_ADDR	= 16
+};
+
+static irq_pio_range_t cuda_ranges[] = {
+	{
+		.base = 0,
+		.size = sizeof(cuda_t) 
+	}
 };
 
@@ -130,4 +137,6 @@
 
 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
@@ -255,7 +264,4 @@
 		return -1;
 	
-	if (sysinfo_get_value("cuda.address.kernel", &(instance->cuda_kernel)) != EOK)
-		return -1;
-	
 	void *vaddr;
 	if (pio_enable((void *) instance->cuda_physical, sizeof(cuda_t), &vaddr) != 0)
@@ -274,5 +280,6 @@
 	pio_write_8(&dev->ier, IER_CLR | ALL_INT);
 
-	cuda_irq_code.cmds[0].addr = (void *) &((cuda_t *) instance->cuda_kernel)->ifr;
+	cuda_irq_code.ranges[0].base = (uintptr_t) instance->cuda_physical;
+	cuda_irq_code.cmds[0].addr = (void *) &((cuda_t *) instance->cuda_physical)->ifr;
 	async_set_interrupt_received(cuda_irq_handler);
 	irq_register(10, device_assign_devno(), 0, &cuda_irq_code);
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.h
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.h	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.h	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -111,5 +111,4 @@
 	cuda_t *cuda;
 	uintptr_t cuda_physical;
-	uintptr_t cuda_kernel;
 
 	uint8_t rcv_buf[CUDA_RCV_BUF_SIZE];
Index: uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c
===================================================================
--- uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision 9744f2d9eba439e6ebe03dfc30d5e8c753bafc09)
+++ uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision 39aa8ced119bf7e09823acd7771b7350177a3149)
@@ -60,4 +60,6 @@
 
 static irq_code_t uart_irq_code = {
+	0,
+	NULL,
 	sizeof(uart_irq_cmds) / sizeof(irq_cmd_t),
 	uart_irq_cmds
