Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 077bc5b99e194570a50d064b2ca7673376920aa6)
+++ kernel/generic/src/ipc/irq.c	(revision a996ae31af28626eb224d0fc0318932c1f196c19)
@@ -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,85 @@
 #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++) {
+		if ((void *) ranges[i].base >= IO_SPACE_BOUNDARY)
+			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++) {
+		if ((void *) ranges[i].base < IO_SPACE_BOUNDARY)
+			continue;
+		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;
+
+		/* Process only commands that use an address. */
+		switch (cmds[i].cmd) {
+		case CMD_PIO_READ_8:
+        	case CMD_PIO_READ_16:
+        	case CMD_PIO_READ_32:
+        	case CMD_PIO_WRITE_8:
+        	case CMD_PIO_WRITE_16:
+        	case CMD_PIO_WRITE_32:
+        	case CMD_PIO_WRITE_A_8:
+        	case CMD_PIO_WRITE_A_16:
+        	case CMD_PIO_WRITE_A_32:
+			break;
+		default:
+			/* Move onto the next command. */
+			continue;
+		}
+
+		addr = (uintptr_t) cmds[i].addr;
+		
+		/* Process only memory mapped PIO addresses. */
+		if ((void *) addr < IO_SPACE_BOUNDARY)
+			continue;
+
+		for (j = 0; j < rangecount; j++) {
+
+			/* Find the matching range. */
+			if (!iswithin(pbase[j], ranges[j].size, addr, 1))
+				continue;
+
+			/* Switch the command to a kernel virtual address. */
+			addr -= pbase[j];
+			addr += ranges[j].base;
+
+			cmds[i].addr = (void *) addr;
+			break;
+		} 
+	}
+
+	free(pbase);
+	return EOK;
+}
 
 /** Free the top-half pseudocode.
@@ -90,4 +173,6 @@
 {
 	if (code) {
+		ranges_unmap(code->ranges, code->rangecount);
+		free(code->ranges);
 		free(code->cmds);
 		free(code);
@@ -104,27 +189,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;
 }
 
@@ -366,8 +469,4 @@
 	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;
