Index: abi/include/ddi/irq.h
===================================================================
--- abi/include/ddi/irq.h	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ abi/include/ddi/irq.h	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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: boot/arch/ia64/src/pal_asm.S
===================================================================
--- boot/arch/ia64/src/pal_asm.S	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ boot/arch/ia64/src/pal_asm.S	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -32,11 +32,16 @@
 
 pal_static_call:
-	alloc loc0 = ar.pfs, 7, 5, 0, 0
+	alloc loc0 = ar.pfs, 7, 6, 0, 0
+
+	mov loc1 = psr ;;
+	mov psr.l = r0 ;;
+	srlz.i
+	srlz.d
 	
-	mov loc1 = gp
-	mov loc2 = rp
+	mov loc2 = gp
+	mov loc3 = rp
 	
-	addl loc3 = @gprel(pal_proc), gp
-	
+	addl loc4 = @gprel(pal_proc), gp
+
 	mov r28 = in0
 	mov r29 = in1
@@ -44,12 +49,16 @@
 	mov r31 = in3 ;;
 	
-	ld8 loc3 = [loc3]
-	movl loc4 = 0f ;;
+	ld8 loc4 = [loc4]
+	movl loc5 = 0f ;;
 
-	mov b6 = loc3
-	mov rp = loc4 ;;
+	mov b6 = loc4
+	mov rp = loc5 ;;
 	br.cond.sptk.many b6
 
 0:
+	mov psr.l = loc1 ;;
+	srlz.i
+	srlz.d
+
 	cmp.ne p7,p0 = 0, in4
 	cmp.ne p8,p0 = 0, in5
@@ -60,6 +69,6 @@
 (p9)	st8 [in6] = r11
 	
-	mov gp = loc1
-	mov rp = loc2 ;;
+	mov gp = loc2
+	mov rp = loc3 ;;
 	
 	mov ar.pfs = loc0
Index: boot/arch/ia64/src/sal_asm.S
===================================================================
--- boot/arch/ia64/src/sal_asm.S	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ boot/arch/ia64/src/sal_asm.S	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -29,4 +29,9 @@
 .explicit
 
+#define STACK_SCRATCH_AREA	16
+#define STACK_IN8		(0 + STACK_SCRATCH_AREA)
+#define STACK_IN9		(8 + STACK_SCRATCH_AREA)
+#define STACK_IN10		(16 + STACK_SCRATCH_AREA)
+
 .global sal_call
 
@@ -39,6 +44,8 @@
 #
 sal_call:
-	alloc loc0 = ar.pfs, 11, 5, 8, 0
+	alloc loc0 = ar.pfs, 8, 8, 8, 0
 	
+	adds sp = -STACK_SCRATCH_AREA, sp
+
 	mov loc1 = gp
 	mov loc2 = rp
@@ -57,20 +64,31 @@
 	
 	ld8 loc3 = [loc3]
-	ld8 gp = [loc4] ;;
+	ld8 gp = [loc4]
+
+	adds r14 = STACK_IN8 + STACK_SCRATCH_AREA, sp
+	adds r15 = STACK_IN9 + STACK_SCRATCH_AREA, sp
+	adds r16 = STACK_IN10 + STACK_SCRATCH_AREA, sp ;;
+
+	ld8 loc5 = [r14]
+	ld8 loc6 = [r15]
+	ld8 loc7 = [r16]
 	
 	mov b6 = loc3 ;;
 	br.call.sptk.many rp = b6
 	
-	cmp.ne p7,p0 = 0, in8
-	cmp.ne p8,p0 = 0, in9
-	cmp.ne p9,p0 = 0, in10 ;;
+	cmp.ne p7,p0 = 0, loc5 
+	cmp.ne p8,p0 = 0, loc6 
+	cmp.ne p9,p0 = 0, loc7 ;;
 	
-(p7)	st8 [in8] = r9
-(p8)	st8 [in9] = r10
-(p9)	st8 [in10] = r11
+(p7)	st8 [loc5] = r9
+(p8)	st8 [loc6] = r10
+(p9)	st8 [loc7] = r11
 	
 	mov gp = loc1
-	mov rp = loc2 ;;
+	mov rp = loc2
+
+	adds sp = STACK_SCRATCH_AREA, sp ;;
 	
 	mov ar.pfs = loc0
 	br.ret.sptk.many rp
+
Index: kernel/arch/arm32/src/mach/integratorcp/integratorcp.c
===================================================================
--- kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/arch/arm32/src/mach/testarm/testarm.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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/include/asm.h
===================================================================
--- kernel/arch/ia64/include/asm.h	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/arch/ia64/include/asm.h	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -61,4 +61,5 @@
 	asm volatile (
 		"mf\n"
+		"mf.a\n"
 		::: "memory"
 	);
@@ -74,4 +75,5 @@
 	asm volatile (
 		"mf\n"
+		"mf.a\n"
 		::: "memory"
 	);
@@ -87,4 +89,5 @@
 	asm volatile (
 		"mf\n"
+		"mf.a\n"
 		::: "memory"
 	);
@@ -104,4 +107,9 @@
 	else
 		v = *port;
+
+	asm volatile (
+		"mf.a\n"
+		::: "memory"
+	);
 	
 	return v;
@@ -121,4 +129,9 @@
 	else
 		v = *port;
+
+	asm volatile (
+		"mf.a\n"
+		::: "memory"
+	);
 	
 	return v;
@@ -138,4 +151,9 @@
 	else
 		v = *port;
+
+	asm volatile (
+		"mf.a\n"
+		::: "memory"
+	);
 
 	return v;
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/arch/ia64/src/ia64.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -144,5 +144,5 @@
 #endif
 #ifdef MACHINE_i460GX
-	platform = "i460GX";
+	platform = "pc";
 #endif
 	sysinfo_set_item_data("platform", NULL, (void *) platform,
@@ -187,6 +187,4 @@
 	sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
 	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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/arch/mips32/src/mips32.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/arch/ppc32/src/ppc32.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/arch/sparc64/src/drivers/kbd.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/generic/include/ddi/irq.h	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/generic/include/ipc/irq.h	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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/include/macros.h
===================================================================
--- kernel/generic/include/macros.h	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/generic/include/macros.h	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -69,7 +69,16 @@
     uint64_t sz2)
 {
-	uint64_t e1 = s1 + sz1;
-	uint64_t e2 = s2 + sz2;
-	
+	uint64_t e1;
+	uint64_t e2;
+
+	/* Handle the two corner cases when either sz1 or sz2 are zero. */
+	if (sz1 == 0)
+		return (s1 == s2) && (sz2 == 0);
+	e1 = s1 + sz1 - 1;	
+	if (sz2 == 0)
+		return (s1 <= s2) && (s2 <= e1);
+	e2 = s2 + sz2 - 1;
+
+	/* e1 and e2 are end addresses, the sum is imune to overflow */
 	return ((s1 <= s2) && (e1 >= e2));
 }
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/generic/src/ipc/irq.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/generic/src/main/main.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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/mm/km.c
===================================================================
--- kernel/generic/src/mm/km.c	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/generic/src/mm/km.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -134,4 +134,5 @@
 	ASSERT(ALIGN_UP(size, FRAME_SIZE) == size);
 
+	/* Enforce natural or at least PAGE_SIZE alignment. */
 	align = ispwr2(size) ? size : (1U << (fnzb(size) + 1));
 	vaddr = km_page_alloc(size, max(PAGE_SIZE, align));
Index: kernel/generic/src/mm/page.c
===================================================================
--- kernel/generic/src/mm/page.c	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/generic/src/mm/page.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -168,9 +168,9 @@
 int page_find_mapping(uintptr_t virt, void **phys)
 {
-	mutex_lock(&AS->lock);
+	page_table_lock(AS, true);
 	
 	pte_t *pte = page_mapping_find(AS, virt, false);
 	if ((!PTE_VALID(pte)) || (!PTE_PRESENT(pte))) {
-		mutex_unlock(&AS->lock);
+		page_table_unlock(AS, true);
 		return ENOENT;
 	}
@@ -179,5 +179,5 @@
 	    (virt - ALIGN_DOWN(virt, PAGE_SIZE));
 	
-	mutex_unlock(&AS->lock);
+	page_table_unlock(AS, true);
 	
 	return EOK;
Index: kernel/generic/src/syscall/copy.c
===================================================================
--- kernel/generic/src/syscall/copy.c	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ kernel/generic/src/syscall/copy.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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*/ },
-	{ .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = 0 /*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,39 +96,22 @@
  * @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;
+	ohci_regs_t *registers = (ohci_regs_t *) regs;
+	cmds[0].addr = (void *) &registers->interrupt_status;
 	cmds[1].value = OHCI_USED_INTERRUPTS;
-	cmds[3].addr = address;
+	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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/drv/bus/usb/ohci/hc.h	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/drv/bus/usb/uhci/hc.h	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/drv/bus/usb/uhci/uhci.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/drv/char/i8042/i8042.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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/infrastructure/root/root.c
===================================================================
--- uspace/drv/infrastructure/root/root.c	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/drv/infrastructure/root/root.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -158,6 +158,9 @@
 	if (asprintf(&match_id, PLATFORM_FUN_MATCH_ID_FMT, platform) == -1) {
 		ddf_msg(LVL_ERROR, "Memory allocation failed.");
-		return ENOMEM;
-	}
+		free(platform);
+		return ENOMEM;
+	}
+
+	free(platform);
 
 	/* Add function. */
@@ -169,4 +172,5 @@
 	if (fun == NULL) {
 		ddf_msg(LVL_ERROR, "Error creating function %s", name);
+		free(match_id);
 		return ENOMEM;
 	}
@@ -176,4 +180,5 @@
 		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
 		    name);
+		free(match_id);
 		ddf_fun_destroy(fun);
 		return rc;
@@ -208,5 +213,5 @@
 	 * vital for the system.
 	 */
-	add_virtual_root_fun(dev);
+	(void) add_virtual_root_fun(dev);
 
 	/* Register root device's children. */
Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/drv/nic/e1k/e1k.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/drv/nic/rtl8139/driver.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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/c/arch/ia64/include/ddi.h
===================================================================
--- uspace/lib/c/arch/ia64/include/ddi.h	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/lib/c/arch/ia64/include/ddi.h	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -62,4 +62,5 @@
 
 	asm volatile ("mf\n" ::: "memory");
+	asm volatile ("mf.a\n" ::: "memory");
 }
 
@@ -76,4 +77,5 @@
 
 	asm volatile ("mf\n" ::: "memory");
+	asm volatile ("mf.a\n" ::: "memory");
 }
 
@@ -90,4 +92,5 @@
 
 	asm volatile ("mf\n" ::: "memory");
+	asm volatile ("mf.a\n" ::: "memory");
 }
 
@@ -106,4 +109,6 @@
 		v = *port;
 	}
+
+	asm volatile ("mf.a\n" ::: "memory");
 
 	return v;
@@ -125,4 +130,6 @@
 	}
 
+	asm volatile ("mf.a\n" ::: "memory");
+
 	return v;
 }
@@ -134,5 +141,5 @@
 	asm volatile ("mf\n" ::: "memory");
 
-	if (port < (ioport32_t *) port) {
+	if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
 		uintptr_t prt = (uintptr_t) port;
 
@@ -143,4 +150,6 @@
 	}
 
+	asm volatile ("mf.a\n" ::: "memory");
+
 	return v;
 }
Index: uspace/lib/drv/generic/interrupt.c
===================================================================
--- uspace/lib/drv/generic/interrupt.c	(revision b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/lib/drv/generic/interrupt.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/srv/hid/input/port/gxemul.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/srv/hid/input/port/msim.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/srv/hid/input/port/ns16550.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/srv/hid/input/port/pl050.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.h	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -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 b9bbaad97903730d588d9d664e11938e5f72c009)
+++ uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision 0a208110cba0d6fad99eb3113730a71b314eefdc)
@@ -60,4 +60,6 @@
 
 static irq_code_t uart_irq_code = {
+	0,
+	NULL,
 	sizeof(uart_irq_cmds) / sizeof(irq_cmd_t),
 	uart_irq_cmds
