Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision ec12ab893015bb2f77916355e67e90d5be826a58)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision f943dd3a2cd9254e12af5d91b1f7097a2c5a6870)
@@ -47,10 +47,16 @@
     (I_SO | I_WDH | I_UE | I_RHSC)
 
-static const irq_cmd_t ohci_irq_commands[] =
-{
-	{ .cmd = CMD_PIO_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_PIO_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;
 }
