Index: uspace/drv/audio/sb16/main.c
===================================================================
--- uspace/drv/audio/sb16/main.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/audio/sb16/main.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -49,7 +49,6 @@
 
 static int sb_add_device(ddf_dev_t *device);
-static int sb_get_res(ddf_dev_t *device, uintptr_t *sb_regs,
-    size_t *sb_regs_size, uintptr_t *mpu_regs, size_t *mpu_regs_size,
-    int *irq, int *dma8, int *dma16);
+static int sb_get_res(ddf_dev_t *device, addr_range_t **pp_sb_regs,
+    addr_range_t **pp_mpu_regs, int *irq, int *dma8, int *dma16);
 static int sb_enable_interrupts(ddf_dev_t *device);
 
@@ -103,10 +102,11 @@
 	}
 
-	uintptr_t sb_regs = 0, mpu_regs = 0;
-	size_t sb_regs_size = 0, mpu_regs_size = 0;
+	addr_range_t sb_regs;
+	addr_range_t *p_sb_regs = &sb_regs;
+	addr_range_t mpu_regs;
+	addr_range_t *p_mpu_regs = &mpu_regs;
 	int irq = 0, dma8 = 0, dma16 = 0;
 
-	rc = sb_get_res(device, &sb_regs, &sb_regs_size, &mpu_regs,
-	    &mpu_regs_size, &irq, &dma8, &dma16);
+	rc = sb_get_res(device, &p_sb_regs, &p_mpu_regs, &irq, &dma8, &dma16);
 	if (rc != EOK) {
 		ddf_log_error("Failed to get resources: %s.", str_error(rc));
@@ -114,5 +114,5 @@
 	}
 
-	sb16_irq_code((void*)sb_regs, dma8, dma16, irq_cmds, irq_ranges);
+	sb16_irq_code(p_sb_regs, dma8, dma16, irq_cmds, irq_ranges);
 
 	irq_code_t irq_code = {
@@ -139,6 +139,5 @@
 	}
 
-	rc = sb16_init_sb16(soft_state, (void*)sb_regs, sb_regs_size, device,
-	    dma8, dma16);
+	rc = sb16_init_sb16(soft_state, p_sb_regs, device, dma8, dma16);
 	if (rc != EOK) {
 		ddf_log_error("Failed to init sb16 driver: %s.",
@@ -147,5 +146,5 @@
 	}
 
-	rc = sb16_init_mpu(soft_state, (void*)mpu_regs, mpu_regs_size);
+	rc = sb16_init_mpu(soft_state, p_mpu_regs);
 	if (rc == EOK) {
 		ddf_fun_t *mpu_fun =
@@ -173,7 +172,6 @@
 }
 
-static int sb_get_res(ddf_dev_t *device, uintptr_t *sb_regs,
-    size_t *sb_regs_size, uintptr_t *mpu_regs, size_t *mpu_regs_size,
-    int *irq, int *dma8, int *dma16)
+static int sb_get_res(ddf_dev_t *device, addr_range_t **pp_sb_regs,
+    addr_range_t **pp_mpu_regs, int *irq, int *dma8, int *dma16)
 {
 	assert(device);
@@ -225,23 +223,18 @@
 	}
 
-
 	if (hw_res.io_ranges.count == 1) {
-		if (sb_regs)
-			*sb_regs = hw_res.io_ranges.ranges[0].address;
-		if (sb_regs_size)
-			*sb_regs_size = hw_res.io_ranges.ranges[0].size;
+		if (pp_sb_regs && *pp_sb_regs)
+			**pp_sb_regs = hw_res.io_ranges.ranges[0];
+		if (pp_mpu_regs)
+			*pp_mpu_regs = NULL;
 	} else {
 		const int sb =
 		    (hw_res.io_ranges.ranges[0].size >= sizeof(sb16_regs_t))
-		        ? 1 : 0;
+		        ? 0 : 1;
 		const int mpu = 1 - sb;
-		if (sb_regs)
-			*sb_regs = hw_res.io_ranges.ranges[sb].address;
-		if (sb_regs_size)
-			*sb_regs_size = hw_res.io_ranges.ranges[sb].size;
-		if (mpu_regs)
-			*sb_regs = hw_res.io_ranges.ranges[mpu].address;
-		if (mpu_regs_size)
-			*sb_regs_size = hw_res.io_ranges.ranges[mpu].size;
+		if (pp_sb_regs && *pp_sb_regs)
+			**pp_sb_regs = hw_res.io_ranges.ranges[sb];
+		if (pp_mpu_regs && *pp_mpu_regs)
+			**pp_mpu_regs = hw_res.io_ranges.ranges[mpu];
 	}
 
@@ -261,4 +254,5 @@
 	return enabled ? EOK : EIO;
 }
+
 /**
  * @}
Index: uspace/drv/audio/sb16/sb16.c
===================================================================
--- uspace/drv/audio/sb16/sb16.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/audio/sb16/sb16.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -77,16 +77,18 @@
 }
 
-void sb16_irq_code(void *regs, int dma8, int dma16, irq_cmd_t cmds[], irq_pio_range_t ranges[])
+void sb16_irq_code(addr_range_t *regs, int dma8, int dma16, irq_cmd_t cmds[],
+    irq_pio_range_t ranges[])
 {
 	assert(regs);
 	assert(dma8 > 0 && dma8 < 4);
-	sb16_regs_t *registers = regs;
+
+	sb16_regs_t *registers = RNGABSPTR(*regs);
 	memcpy(cmds, irq_cmds, sizeof(irq_cmds));
-	cmds[0].addr = (void*)&registers->dsp_read_status;
-	ranges[0].base = (uintptr_t)registers;
+	cmds[0].addr = (void *) &registers->dsp_read_status;
+	ranges[0].base = (uintptr_t) registers;
 	ranges[0].size = sizeof(*registers);
 	if (dma16 > 4 && dma16 < 8) {
 		/* Valid dma16 */
-		cmds[1].addr = (void*)&registers->dma16_ack;
+		cmds[1].addr = (void *) &registers->dma16_ack;
 	} else {
 		cmds[1].cmd = CMD_ACCEPT;
@@ -94,13 +96,14 @@
 }
 
-int sb16_init_sb16(sb16_t *sb, void *regs, size_t size,
-    ddf_dev_t *dev, int dma8, int dma16)
+int sb16_init_sb16(sb16_t *sb, addr_range_t *regs, ddf_dev_t *dev, int dma8,
+    int dma16)
 {
 	assert(sb);
+
 	/* Setup registers */
-	int ret = pio_enable(regs, size, (void**)&sb->regs);
+	int ret = pio_enable_range(regs, (void **) &sb->regs);
 	if (ret != EOK)
 		return ret;
-	ddf_log_debug("PIO registers at %p accessible.", sb->regs);
+	ddf_log_note("PIO registers at %p accessible.", sb->regs);
 
 	/* Initialize DSP */
@@ -187,5 +190,5 @@
 }
 
-int sb16_init_mpu(sb16_t *sb, void *regs, size_t size)
+int sb16_init_mpu(sb16_t *sb, addr_range_t *regs)
 {
 	sb->mpu_regs = NULL;
Index: uspace/drv/audio/sb16/sb16.h
===================================================================
--- uspace/drv/audio/sb16/sb16.h	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/audio/sb16/sb16.h	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -38,4 +38,5 @@
 #include <ddf/driver.h>
 #include <ddi.h>
+#include <device/hw_res_parsed.h>
 
 #include "dsp.h"
@@ -51,8 +52,7 @@
 
 size_t sb16_irq_code_size(void);
-void sb16_irq_code(void *regs, int dma8, int dma16, irq_cmd_t cmds[], irq_pio_range_t ranges[]);
-int sb16_init_sb16(sb16_t *sb, void *regs, size_t size,
-    ddf_dev_t *dev, int dma8, int dma16);
-int sb16_init_mpu(sb16_t *sb, void *regs, size_t size);
+void sb16_irq_code(addr_range_t *regs, int dma8, int dma16, irq_cmd_t cmds[], irq_pio_range_t ranges[]);
+int sb16_init_sb16(sb16_t *sb, addr_range_t *regs, ddf_dev_t *dev, int dma8, int dma16);
+int sb16_init_mpu(sb16_t *sb, addr_range_t *regs);
 void sb16_interrupt(sb16_t *sb);
 
Index: uspace/drv/block/ahci/ahci.c
===================================================================
--- uspace/drv/block/ahci/ahci.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/block/ahci/ahci.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -1157,5 +1157,5 @@
 	ahci->memregs = NULL;
 	
-	physmem_map((uintptr_t) (hw_res_parsed.mem_ranges.ranges[0].address),
+	physmem_map(RNGABS(hw_res_parsed.mem_ranges.ranges[0]),
 	    AHCI_MEMREGS_PAGES_COUNT, AS_AREA_READ | AS_AREA_WRITE,
 	    (void **) &ahci->memregs);
@@ -1164,5 +1164,5 @@
 	
 	/* Register interrupt handler */
-	ahci_ranges[0].base = (size_t) hw_res_parsed.mem_ranges.ranges[0].address;
+	ahci_ranges[0].base = RNGABS(hw_res_parsed.mem_ranges.ranges[0]);
 	ahci_ranges[0].size = sizeof(ahci_memregs_t);
 	
@@ -1171,5 +1171,5 @@
 		
 		ahci_cmds[base].addr =
-		    ((uint32_t *) (size_t) hw_res_parsed.mem_ranges.ranges[0].address) +
+		    ((uint32_t *) RNGABSPTR(hw_res_parsed.mem_ranges.ranges[0])) +
 		    AHCI_PORTS_REGISTERS_OFFSET + port * AHCI_PORT_REGISTERS_SIZE +
 		    AHCI_PORT_IS_REGISTER_OFFSET;
@@ -1177,5 +1177,5 @@
 		
 		ahci_cmds[base + 3].addr =
-		    ((uint32_t *) (size_t) hw_res_parsed.mem_ranges.ranges[0].address) +
+		    ((uint32_t *) RNGABSPTR(hw_res_parsed.mem_ranges.ranges[0])) +
 		    AHCI_GHC_IS_REGISTER_OFFSET;
 		ahci_cmds[base + 4].addr = ahci_cmds[base + 3].addr;
Index: uspace/drv/block/ata_bd/main.c
===================================================================
--- uspace/drv/block/ata_bd/main.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/block/ata_bd/main.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -84,13 +84,15 @@
 	}
 
-	ata_res->cmd = hw_res.io_ranges.ranges[0].address;
-	ata_res->ctl = hw_res.io_ranges.ranges[1].address;
-
-	if (hw_res.io_ranges.ranges[0].size < sizeof(ata_ctl_t)) {
+	addr_range_t *cmd_rng = &hw_res.io_ranges.ranges[0];
+	addr_range_t *ctl_rng = &hw_res.io_ranges.ranges[1];
+	ata_res->cmd = RNGABS(*cmd_rng);
+	ata_res->ctl = RNGABS(*ctl_rng);
+
+	if (RNGSZ(*ctl_rng) < sizeof(ata_ctl_t)) {
 		rc = EINVAL;
 		goto error;
 	}
 
-	if (hw_res.io_ranges.ranges[1].size < sizeof(ata_cmd_t)) {
+	if (RNGSZ(*cmd_rng) < sizeof(ata_cmd_t)) {
 		rc = EINVAL;
 		goto error;
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/isa/isa.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -65,4 +65,5 @@
 #include <ddf/log.h>
 #include <ops/hw_res.h>
+#include <ops/pio_window.h>
 
 #include <device/hw_res.h>
@@ -104,10 +105,10 @@
 }
 
-static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode)
-{
-	isa_fun_t *isa = isa_fun(fnode);
-	assert(isa);
-
-	return &isa->hw_resources;
+static hw_resource_list_t *isa_fun_get_resources(ddf_fun_t *fnode)
+{
+	isa_fun_t *fun = isa_fun(fnode);
+	assert(fun);
+
+	return &fun->hw_resources;
 }
 
@@ -116,6 +117,6 @@
 	/* This is an old ugly way, copied from pci driver */
 	assert(fnode);
-	isa_fun_t *isa = isa_fun(fnode);
-	assert(isa);
+	isa_fun_t *fun = isa_fun(fnode);
+	assert(fun);
 
 	sysarg_t apic;
@@ -133,5 +134,5 @@
 		return false;
 
-	const hw_resource_list_t *res = &isa->hw_resources;
+	const hw_resource_list_t *res = &fun->hw_resources;
 	assert(res);
 	for (size_t i = 0; i < res->count; ++i) {
@@ -159,7 +160,7 @@
 {
 	assert(fnode);
-	isa_fun_t *isa = isa_fun(fnode);
-	assert(isa);
-	const hw_resource_list_t *res = &isa->hw_resources;
+	isa_fun_t *fun = isa_fun(fnode);
+	assert(fun);
+	const hw_resource_list_t *res = &fun->hw_resources;
 	assert(res);
 
@@ -182,7 +183,7 @@
 	assert(size);
 	assert(fnode);
-	isa_fun_t *isa = isa_fun(fnode);
-	assert(isa);
-	const hw_resource_list_t *res = &isa->hw_resources;
+	isa_fun_t *fun = isa_fun(fnode);
+	assert(fun);
+	const hw_resource_list_t *res = &fun->hw_resources;
 	assert(res);
 
@@ -201,5 +202,5 @@
 
 static hw_res_ops_t isa_fun_hw_res_ops = {
-	.get_resource_list = isa_get_fun_resources,
+	.get_resource_list = isa_fun_get_resources,
 	.enable_interrupt = isa_fun_enable_interrupt,
 	.dma_channel_setup = isa_fun_setup_dma,
@@ -207,6 +208,20 @@
 };
 
+static pio_window_t *isa_fun_get_pio_window(ddf_fun_t *fnode)
+{
+	ddf_dev_t *dev = ddf_fun_get_dev(fnode);
+	isa_bus_t *isa = isa_bus(dev);
+	assert(isa);
+
+	return &isa->pio_win;
+}
+
+static pio_window_ops_t isa_fun_pio_window_ops = {
+	.get_pio_window = isa_fun_get_pio_window
+};
+
 static ddf_dev_ops_t isa_fun_ops= {
 	.interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops,
+	.interfaces[PIO_WINDOW_DEV_IFACE] = &isa_fun_pio_window_ops,
 };
 
@@ -414,4 +429,5 @@
 		resources[count].res.io_range.address += isa->pio_win.io.base;
 		resources[count].res.io_range.size = len;
+		resources[count].res.io_range.relative = false;
 		resources[count].res.io_range.endianness = LITTLE_ENDIAN;
 
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -256,5 +256,5 @@
 	fibril_mutex_lock(&bus->conf_mutex);
 
-	pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
+	pio_write_32(bus->conf_addr_reg, host2uint32_t_le(conf_addr));
 
 	/*
@@ -263,5 +263,5 @@
 	 * support shorter PIO reads offset from this register.
  	 */
-	val = uint32_t_le2host(pio_read_32(bus->conf_data_port));
+	val = uint32_t_le2host(pio_read_32(bus->conf_data_reg));
 
 	switch (len) {
@@ -299,6 +299,6 @@
  		 * missing bits first.
  		 */
-		pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
-		val = uint32_t_le2host(pio_read_32(bus->conf_data_port));
+		pio_write_32(bus->conf_addr_reg, host2uint32_t_le(conf_addr));
+		val = uint32_t_le2host(pio_read_32(bus->conf_data_reg));
 	}
 	
@@ -317,6 +317,6 @@
 	}
 
-	pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
-	pio_write_32(bus->conf_data_port, host2uint32_t_le(val));
+	pio_write_32(bus->conf_addr_reg, host2uint32_t_le(conf_addr));
+	pio_write_32(bus->conf_data_reg, host2uint32_t_le(val));
 	
 	fibril_mutex_unlock(&bus->conf_mutex);
@@ -449,4 +449,5 @@
 		hw_resources[count].res.io_range.address = range_addr;
 		hw_resources[count].res.io_range.size = range_size;
+		hw_resources[count].res.io_range.relative = true;
 		hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN;
 	} else {
@@ -454,4 +455,5 @@
 		hw_resources[count].res.mem_range.address = range_addr;
 		hw_resources[count].res.mem_range.size = range_size;
+		hw_resources[count].res.mem_range.relative = false;
 		hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN;
 	}
@@ -722,17 +724,12 @@
 	    hw_resources.resources[1].res.io_range.address);
 	
-	bus->conf_io_addr =
-	    (uint32_t) hw_resources.resources[0].res.io_range.address;
-	bus->conf_io_data =
-	    (uint32_t) hw_resources.resources[1].res.io_range.address;
-	
-	if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 4,
-	    &bus->conf_addr_port)) {
+	if (pio_enable_resource(&bus->pio_win, &hw_resources.resources[0],
+	    (void **) &bus->conf_addr_reg)) {
 		ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
 		rc = EADDRNOTAVAIL;
 		goto fail;
 	}
-	if (pio_enable((void *)(uintptr_t)bus->conf_io_data, 4,
-	    &bus->conf_data_port)) {
+	if (pio_enable_resource(&bus->pio_win, &hw_resources.resources[1],
+	    (void **) &bus->conf_data_reg)) {
 		ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
 		rc = EADDRNOTAVAIL;
Index: uspace/drv/bus/pci/pciintel/pci.h
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.h	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/pci/pciintel/pci.h	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -45,8 +45,6 @@
 	/** DDF device node */
 	ddf_dev_t *dnode;
-	uint32_t conf_io_addr;
-	uint32_t conf_io_data;
-	void *conf_data_port;
-	void *conf_addr_port;
+	ioport32_t *conf_addr_reg;
+	ioport32_t *conf_data_reg;
 	pio_window_t pio_win;
 	fibril_mutex_t conf_mutex;
Index: uspace/drv/bus/usb/ehci/main.c
===================================================================
--- uspace/drv/bus/usb/ehci/main.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/ehci/main.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -77,9 +77,8 @@
 	assert(device);
 
-	uintptr_t reg_base = 0;
-	size_t reg_size = 0;
+	addr_range_t reg_range;
 	int irq = 0;
 
-	int rc = get_my_registers(device, &reg_base, &reg_size, &irq);
+	int rc = get_my_registers(device, &reg_range, &irq);
 	if (rc != EOK) {
 		usb_log_error("Failed to get memory addresses for %" PRIun
@@ -88,8 +87,8 @@
 	}
 
-	usb_log_info("Memory mapped regs at 0x%" PRIxn " (size %zu), IRQ %d.\n",
-	    reg_base, reg_size, irq);
+	usb_log_info("Memory mapped regs at %p (size %zu), IRQ %d.\n",
+	    RNGABSPTR(reg_range), RNGSZ(reg_range), irq);
 
-	rc = disable_legacy(device, reg_base, reg_size);
+	rc = disable_legacy(device, &reg_range);
 	if (rc != EOK) {
 		usb_log_error("Failed to disable legacy USB: %s.\n",
Index: uspace/drv/bus/usb/ehci/res.c
===================================================================
--- uspace/drv/bus/usb/ehci/res.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/ehci/res.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -71,11 +71,10 @@
  *
  * @param[in] dev Device asking for the addresses.
- * @param[out] mem_reg_address Base address of the memory range.
- * @param[out] mem_reg_size Size of the memory range.
+ * @param[out] mem_regs_p Pointer to the register range.
  * @param[out] irq_no IRQ assigned to the device.
  * @return Error code.
  */
 int get_my_registers(ddf_dev_t *dev,
-    uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
+    addr_range_t *mem_regs_p, int *irq_no)
 {
 	assert(dev);
@@ -99,8 +98,6 @@
 	}
 
-	if (mem_reg_address)
-		*mem_reg_address = hw_res.mem_ranges.ranges[0].address;
-	if (mem_reg_size)
-		*mem_reg_size = hw_res.mem_ranges.ranges[0].size;
+	if (mem_regs_p)
+		*mem_regs_p = hw_res.mem_ranges.ranges[0];
 	if (irq_no)
 		*irq_no = hw_res.irqs.irqs[0];
@@ -267,5 +264,5 @@
 }
 
-int disable_legacy(ddf_dev_t *device, uintptr_t reg_base, size_t reg_size)
+int disable_legacy(ddf_dev_t *device, addr_range_t *reg_range)
 {
 	assert(device);
@@ -274,8 +271,8 @@
 	/* Map EHCI registers */
 	void *regs = NULL;
-	int rc = pio_enable((void*)reg_base, reg_size, &regs);
+	int rc = pio_enable_range(reg_range, &regs);
 	if (rc != EOK) {
 		usb_log_error("Failed to map registers %p: %s.\n",
-		    (void *) reg_base, str_error(rc));
+		    RNGABSPTR(*reg_range), str_error(rc));
 		return rc;
 	}
Index: uspace/drv/bus/usb/ehci/res.h
===================================================================
--- uspace/drv/bus/usb/ehci/res.h	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/ehci/res.h	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -37,8 +37,9 @@
 
 #include <ddf/driver.h>
+#include <device/hw_res_parsed.h>
 
-int get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
+int get_my_registers(ddf_dev_t *, addr_range_t *, int *);
 int enable_interrupts(ddf_dev_t *);
-int disable_legacy(ddf_dev_t *, uintptr_t, size_t);
+int disable_legacy(ddf_dev_t *, addr_range_t *);
 
 #endif
Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -106,6 +106,5 @@
  * @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).
+ * @param[in] regs Device's register range.
  *
  * @return Error code.
@@ -113,16 +112,16 @@
 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)
+    size_t cmds_size, addr_range_t *regs)
 {
 	if ((ranges_size < sizeof(ohci_pio_ranges)) ||
 	    (cmds_size < sizeof(ohci_irq_commands)) ||
-	    (reg_size < sizeof(ohci_regs_t)))
+	    (RNGSZ(*regs) < sizeof(ohci_regs_t)))
 		return EOVERFLOW;
 
 	memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges));
-	ranges[0].base = regs;
+	ranges[0].base = RNGABS(*regs);
 
 	memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
-	ohci_regs_t *registers = (ohci_regs_t *) regs;
+	ohci_regs_t *registers = (ohci_regs_t *) RNGABSPTR(*regs);
 	cmds[0].addr = (void *) &registers->interrupt_status;
 	cmds[3].addr = (void *) &registers->interrupt_status;
@@ -135,6 +134,5 @@
  *
  * @param[in] device Host controller DDF device
- * @param[in] reg_base Register range base
- * @param[in] reg_size Register range size
+ * @param[in] regs Register range
  * @param[in] irq Interrupt number
  * @paran[in] handler Interrupt handler
@@ -142,6 +140,6 @@
  * @return EOK on success or negative error code
  */
-int hc_register_irq_handler(ddf_dev_t *device, uintptr_t reg_base, size_t reg_size,
-    int irq, interrupt_handler_t handler)
+int hc_register_irq_handler(ddf_dev_t *device, addr_range_t *regs, int irq,
+    interrupt_handler_t handler)
 {
 	int rc;
@@ -158,5 +156,5 @@
 
 	rc = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
-	    sizeof(irq_cmds), reg_base, reg_size);
+	    sizeof(irq_cmds), regs);
 	if (rc != EOK) {
 		usb_log_error("Failed to generate IRQ code: %s.\n",
@@ -259,15 +257,13 @@
  *
  * @param[in] instance Memory place for the structure.
- * @param[in] regs Address of the memory mapped I/O registers.
- * @param[in] reg_size Size of the memory mapped area.
+ * @param[in] regs Device's I/O registers range.
  * @param[in] interrupts True if w interrupts should be used
  * @return Error code
  */
-int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts)
-{
-	assert(instance);
-
-	int rc =
-	    pio_enable((void*)regs, reg_size, (void**)&instance->registers);
+int hc_init(hc_t *instance, addr_range_t *regs, bool interrupts)
+{
+	assert(instance);
+
+	int rc = pio_enable_range(regs, (void **) &instance->registers);
 	if (rc != EOK) {
 		usb_log_error("Failed to gain access to device registers: %s.\n",
Index: uspace/drv/bus/usb/ohci/hc.h
===================================================================
--- uspace/drv/bus/usb/ohci/hc.h	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/ohci/hc.h	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -75,9 +75,10 @@
 } hc_t;
 
-int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, uintptr_t,
-    size_t);
-int hc_register_irq_handler(ddf_dev_t *, uintptr_t, size_t, int, interrupt_handler_t);
+int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t,
+    addr_range_t *);
+int hc_register_irq_handler(ddf_dev_t *, addr_range_t *, int,
+    interrupt_handler_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);
+int hc_init(hc_t *instance, addr_range_t *regs, bool interrupts);
 
 /** Safely dispose host controller internal structures
Index: uspace/drv/bus/usb/ohci/ohci.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -177,9 +177,8 @@
 	ddf_fun_set_ops(instance->rh_fun, &rh_ops);
 
-	uintptr_t reg_base = 0;
-	size_t reg_size = 0;
+	addr_range_t regs;
 	int irq = 0;
 
-	rc = get_my_registers(device, &reg_base, &reg_size, &irq);
+	rc = get_my_registers(device, &regs, &irq);
 	if (rc != EOK) {
 		usb_log_error("Failed to get register memory addresses "
@@ -190,7 +189,7 @@
 
 	usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
-	    (void *) reg_base, reg_size, irq);
-
-	rc = hc_register_irq_handler(device, reg_base, reg_size, irq, irq_handler);
+	    RNGABSPTR(regs), RNGSZ(regs), irq);
+
+	rc = hc_register_irq_handler(device, &regs, irq, irq_handler);
 	if (rc != EOK) {
 		usb_log_error("Failed to register interrupt handler: %s.\n",
@@ -215,5 +214,5 @@
 	}
 
-	rc = hc_init(&instance->hc, reg_base, reg_size, interrupts);
+	rc = hc_init(&instance->hc, &regs, interrupts);
 	if (rc != EOK) {
 		usb_log_error("Failed to init ohci_hcd: %s.\n", str_error(rc));
Index: uspace/drv/bus/usb/ohci/res.c
===================================================================
--- uspace/drv/bus/usb/ohci/res.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/ohci/res.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -48,11 +48,9 @@
  *
  * @param[in] dev Device asking for the addresses.
- * @param[out] mem_reg_address Base address of the memory range.
- * @param[out] mem_reg_size Size of the memory range.
+ * @param[out] p_regs Pointer to register range.
  * @param[out] irq_no IRQ assigned to the device.
  * @return Error code.
  */
-int get_my_registers(ddf_dev_t *dev,
-    uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
+int get_my_registers(ddf_dev_t *dev, addr_range_t *p_regs, int *irq_no)
 {
 	assert(dev);
@@ -66,5 +64,5 @@
 	hw_res_list_parsed_t hw_res;
 	hw_res_list_parsed_init(&hw_res);
-	const int ret =  hw_res_get_list_parsed(parent_sess, &hw_res, 0);
+	const int ret = hw_res_get_list_parsed(parent_sess, &hw_res, 0);
 	async_hangup(parent_sess);
 	if (ret != EOK) {
@@ -78,8 +76,6 @@
 	}
 
-	if (mem_reg_address)
-		*mem_reg_address = hw_res.mem_ranges.ranges[0].address;
-	if (mem_reg_size)
-		*mem_reg_size = hw_res.mem_ranges.ranges[0].size;
+	if (p_regs)
+		*p_regs = hw_res.mem_ranges.ranges[0];
 	if (irq_no)
 		*irq_no = hw_res.irqs.irqs[0];
Index: uspace/drv/bus/usb/ohci/res.h
===================================================================
--- uspace/drv/bus/usb/ohci/res.h	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/ohci/res.h	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -36,6 +36,7 @@
 
 #include <ddf/driver.h>
+#include <device/hw_res_parsed.h>
 
-int get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
+int get_my_registers(ddf_dev_t *, addr_range_t *, int *);
 int enable_interrupts(ddf_dev_t *);
 
Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -105,6 +105,5 @@
  * @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).
+ * @param[in] regs Device's register range.
  *
  * @return Error code.
@@ -112,16 +111,16 @@
 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)
+    size_t cmds_size, addr_range_t *regs)
 {
 	if ((ranges_size < sizeof(uhci_irq_pio_ranges)) ||
 	    (cmds_size < sizeof(uhci_irq_commands)) ||
-	    (reg_size < sizeof(uhci_regs_t)))
+	    (RNGSZ(*regs) < sizeof(uhci_regs_t)))
 		return EOVERFLOW;
 
 	memcpy(ranges, uhci_irq_pio_ranges, sizeof(uhci_irq_pio_ranges));
-	ranges[0].base = regs;
+	ranges[0].base = RNGABS(*regs);
 
 	memcpy(cmds, uhci_irq_commands, sizeof(uhci_irq_commands));
-	uhci_regs_t *registers = (uhci_regs_t *) regs;
+	uhci_regs_t *registers = (uhci_regs_t *) RNGABSPTR(*regs);
 	cmds[0].addr = &registers->usbsts;
 	cmds[3].addr = &registers->usbsts;
@@ -133,6 +132,5 @@
  *
  * @param[in] device Host controller DDF device
- * @param[in] reg_base Register range base
- * @param[in] reg_size Register range size
+ * @param[in] regs Register range
  * @param[in] irq Interrupt number
  * @paran[in] handler Interrupt handler
@@ -140,6 +138,6 @@
  * @return EOK on success or negative error code
  */
-int hc_register_irq_handler(ddf_dev_t *device, uintptr_t reg_base, size_t reg_size,
-    int irq, interrupt_handler_t handler)
+int hc_register_irq_handler(ddf_dev_t *device, addr_range_t *regs, int irq,
+    interrupt_handler_t handler)
 {
 	int rc;
@@ -147,5 +145,5 @@
 	irq_cmd_t irq_cmds[hc_irq_cmd_count];
 	rc = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
-	    sizeof(irq_cmds), reg_base, reg_size);
+	    sizeof(irq_cmds), regs);
 	if (rc != EOK) {
 		usb_log_error("Failed to generate IRQ commands: %s.\n",
@@ -232,6 +230,5 @@
  *
  * @param[in] instance Memory place to initialize.
- * @param[in] regs Address of I/O control registers.
- * @param[in] reg_size Size of I/O control registers.
+ * @param[in] regs Range of device's I/O control registers.
  * @param[in] interrupts True if hw interrupts should be used.
  * @return Error code.
@@ -241,7 +238,7 @@
  * interrupt fibrils.
  */
-int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts)
-{
-	assert(reg_size >= sizeof(uhci_regs_t));
+int hc_init(hc_t *instance, addr_range_t *regs, bool interrupts)
+{
+	assert(regs->size >= sizeof(uhci_regs_t));
 	int rc;
 
@@ -251,5 +248,5 @@
 	/* allow access to hc control registers */
 	uhci_regs_t *io;
-	rc = pio_enable(regs, reg_size, (void **)&io);
+	rc = pio_enable_range(regs, (void **) &io);
 	if (rc != EOK) {
 		usb_log_error("Failed to gain access to registers at %p: %s.\n",
@@ -260,5 +257,5 @@
 	instance->registers = io;
 	usb_log_debug(
-	    "Device registers at %p (%zuB) accessible.\n", io, reg_size);
+	    "Device registers at %p (%zuB) accessible.\n", io, regs->size);
 
 	rc = hc_init_mem_structures(instance);
Index: uspace/drv/bus/usb/uhci/hc.h
===================================================================
--- uspace/drv/bus/usb/uhci/hc.h	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/uhci/hc.h	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -37,4 +37,5 @@
 
 #include <ddf/interrupt.h>
+#include <device/hw_res_parsed.h>
 #include <fibril.h>
 #include <usb/host/hcd.h>
@@ -120,9 +121,10 @@
 } hc_t;
 
-int hc_register_irq_handler(ddf_dev_t *, uintptr_t, size_t, int, interrupt_handler_t);
-int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, uintptr_t,
-    size_t);
+int hc_register_irq_handler(ddf_dev_t *, addr_range_t *, int,
+    interrupt_handler_t);
+int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t,
+    addr_range_t *);
 void hc_interrupt(hc_t *instance, uint16_t status);
-int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
+int hc_init(hc_t *instance, addr_range_t *regs, bool interupts);
 
 /** Safely dispose host controller internal structures
@@ -132,4 +134,5 @@
 static inline void hc_fini(hc_t *instance) {} /* TODO: implement*/
 #endif
+
 /**
  * @}
Index: uspace/drv/bus/usb/uhci/res.c
===================================================================
--- uspace/drv/bus/usb/uhci/res.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/uhci/res.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -46,11 +46,9 @@
  *
  * @param[in] dev Device asking for the addresses.
- * @param[out] io_reg_address Base address of the I/O range.
- * @param[out] io_reg_size Size of the I/O range.
+ * @param[out] io_regs_p Pointer to register I/O range.
  * @param[out] irq_no IRQ assigned to the device.
  * @return Error code.
  */
-int get_my_registers(ddf_dev_t *dev,
-    uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no)
+int get_my_registers(ddf_dev_t *dev, addr_range_t *io_regs_p, int *irq_no)
 {
 	assert(dev);
@@ -76,8 +74,6 @@
 	}
 
-	if (io_reg_address)
-		*io_reg_address = hw_res.io_ranges.ranges[0].address;
-	if (io_reg_size)
-		*io_reg_size = hw_res.io_ranges.ranges[0].size;
+	if (io_regs_p)
+		*io_regs_p = hw_res.io_ranges.ranges[0];
 	if (irq_no)
 		*irq_no = hw_res.irqs.irqs[0];
Index: uspace/drv/bus/usb/uhci/res.h
===================================================================
--- uspace/drv/bus/usb/uhci/res.h	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/uhci/res.h	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -37,6 +37,7 @@
 
 #include <ddf/driver.h>
+#include <device/hw_res_parsed.h>
 
-int get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
+int get_my_registers(ddf_dev_t *, addr_range_t *, int *);
 int enable_interrupts(ddf_dev_t *);
 int disable_legacy(ddf_dev_t *);
Index: uspace/drv/bus/usb/uhci/uhci.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/uhci/uhci.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -184,9 +184,8 @@
 	ddf_fun_data_implant(instance->rh_fun, &instance->rh);
 
-	uintptr_t reg_base = 0;
-	size_t reg_size = 0;
+	addr_range_t regs;
 	int irq = 0;
 
-	rc = get_my_registers(device, &reg_base, &reg_size, &irq);
+	rc = get_my_registers(device, &regs, &irq);
 	if (rc != EOK) {
 		usb_log_error("Failed to get I/O addresses for %" PRIun ": %s.\n",
@@ -194,6 +193,6 @@
 		goto error;
 	}
-	usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n",
-	    (void *) reg_base, reg_size, irq);
+	usb_log_debug("I/O regs at %p (size %zu), IRQ %d.\n",
+	    RNGABSPTR(regs), RNGSZ(regs), irq);
 
 	rc = disable_legacy(device);
@@ -204,5 +203,5 @@
 	}
 
-	rc = hc_register_irq_handler(device, reg_base, reg_size, irq, irq_handler);
+	rc = hc_register_irq_handler(device, &regs, irq, irq_handler);
 	if (rc != EOK) {
 		usb_log_error("Failed to register interrupt handler: %s.\n",
@@ -223,5 +222,5 @@
 	}
 
-	rc = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
+	rc = hc_init(&instance->hc, &regs, interrupts);
 	if (rc != EOK) {
 		usb_log_error("Failed to init uhci_hcd: %s.\n", str_error(rc));
Index: uspace/drv/bus/usb/uhcirh/main.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/main.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/uhcirh/main.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -48,6 +48,5 @@
 #define NAME "uhcirh"
 
-static int hc_get_my_registers(ddf_dev_t *dev,
-    uintptr_t *io_reg_address, size_t *io_reg_size);
+static int hc_get_my_registers(ddf_dev_t *dev, addr_range_t *io_regs);
 
 static int uhci_rh_dev_add(ddf_dev_t *device);
@@ -90,10 +89,9 @@
 	    ddf_dev_get_handle(device));
 
-	uintptr_t io_regs = 0;
-	size_t io_size = 0;
+	addr_range_t regs;
 	uhci_root_hub_t *rh = NULL;
 	int rc;
 
-	rc = hc_get_my_registers(device, &io_regs, &io_size);
+	rc = hc_get_my_registers(device, &regs);
 	if (rc != EOK) {
 		usb_log_error( "Failed to get registers from HC: %s.\n",
@@ -103,5 +101,5 @@
 
 	usb_log_debug("I/O regs at %p (size %zuB).\n",
-	    (void *) io_regs, io_size);
+	    RNGABSPTR(regs), RNGSZ(regs));
 
 	rh = ddf_dev_data_alloc(device, sizeof(uhci_root_hub_t));
@@ -111,5 +109,5 @@
 	}
 
-	rc = uhci_root_hub_init(rh, (void*)io_regs, io_size, device);
+	rc = uhci_root_hub_init(rh, &regs, device);
 	if (rc != EOK) {
 		usb_log_error("Failed(%d) to initialize rh driver instance: "
@@ -127,10 +125,8 @@
  *
  * @param[in] dev Device asking for the addresses.
- * @param[out] io_reg_address Base address of the memory range.
- * @param[out] io_reg_size Size of the memory range.
+ * @param[out] io_regs_p Pointer to the device's register range.
  * @return Error code.
  */
-int hc_get_my_registers(
-    ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size)
+int hc_get_my_registers(ddf_dev_t *dev, addr_range_t *io_regs_p)
 {
 	async_sess_t *parent_sess =
@@ -153,9 +149,6 @@
 	}
 
-	if (io_reg_address != NULL)
-		*io_reg_address = hw_res.io_ranges.ranges[0].address;
-
-	if (io_reg_size != NULL)
-		*io_reg_size = hw_res.io_ranges.ranges[0].size;
+	if (io_regs_p != NULL)
+		*io_regs_p = hw_res.io_ranges.ranges[0];
 
 	hw_res_list_parsed_clean(&hw_res);
Index: uspace/drv/bus/usb/uhcirh/root_hub.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/root_hub.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/uhcirh/root_hub.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -36,4 +36,5 @@
 #include <ddi.h>
 #include <usb/debug.h>
+#include <device/hw_res_parsed.h>
 
 #include "root_hub.h"
@@ -42,23 +43,24 @@
  *
  * @param[in] instance Driver memory structure to use.
- * @param[in] addr Address of I/O registers.
- * @param[in] size Size of available I/O space.
+ * @param[in] io_regs Range of I/O registers.
  * @param[in] rh Pointer to DDF instance of the root hub driver.
  * @return Error code.
  */
-int uhci_root_hub_init(
-  uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh)
+int uhci_root_hub_init(uhci_root_hub_t *instance, addr_range_t *io_regs,
+    ddf_dev_t *rh)
 {
+	port_status_t *regs;
+
 	assert(instance);
 	assert(rh);
 
 	/* Allow access to root hub port registers */
-	assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT <= size);
-	port_status_t *regs;
-	int ret = pio_enable(addr, size, (void**)&regs);
+	assert(sizeof(*regs) * UHCI_ROOT_HUB_PORT_COUNT <= io_regs->size);
+
+	int ret = pio_enable_range(io_regs, (void **) &regs);
 	if (ret < 0) {
 		usb_log_error(
 		    "Failed(%d) to gain access to port registers at %p: %s.\n",
-		    ret, regs, str_error(ret));
+		    ret, RNGABSPTR(*io_regs), str_error(ret));
 		return ret;
 	}
Index: uspace/drv/bus/usb/uhcirh/root_hub.h
===================================================================
--- uspace/drv/bus/usb/uhcirh/root_hub.h	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/bus/usb/uhcirh/root_hub.h	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -36,4 +36,5 @@
 
 #include <ddf/driver.h>
+#include <device/hw_res_parsed.h>
 
 #include "port.h"
@@ -48,6 +49,6 @@
 } uhci_root_hub_t;
 
-int uhci_root_hub_init(
-    uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh);
+int uhci_root_hub_init(uhci_root_hub_t *instance, addr_range_t *regs,
+    ddf_dev_t *rh);
 
 void uhci_root_hub_fini(uhci_root_hub_t *instance);
Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/char/i8042/i8042.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -145,6 +145,5 @@
  *
  * @param dev       Driver structure to initialize.
- * @param regs      I/O address of registers.
- * @param reg_size  size of the reserved I/O address space.
+ * @param regs      I/O range  of registers.
  * @param irq_kbd   IRQ for primary port.
  * @param irq_mouse IRQ for aux port.
@@ -154,5 +153,5 @@
  *
  */
-int i8042_init(i8042_t *dev, void *regs, size_t reg_size, int irq_kbd,
+int i8042_init(i8042_t *dev, addr_range_t *regs, int irq_kbd,
     int irq_mouse, ddf_dev_t *ddf_dev)
 {
@@ -162,4 +161,5 @@
 	const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
 	irq_cmd_t cmds[cmd_count];
+	i8042_regs_t *ar;
 
 	int rc;
@@ -170,10 +170,10 @@
 	dev->aux_fun = NULL;
 	
-	if (reg_size < sizeof(i8042_regs_t)) {
+	if (regs->size < sizeof(i8042_regs_t)) {
 		rc = EINVAL;
 		goto error;
 	}
 	
-	if (pio_enable(regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0) {
+	if (pio_enable_range(regs, (void **) &dev->regs) != 0) {
 		rc = EIO;
 		goto error;
@@ -234,9 +234,11 @@
 
 	memcpy(ranges, i8042_ranges, sizeof(i8042_ranges));
-	ranges[0].base = (uintptr_t) regs;
-
+	ranges[0].base = RNGABS(*regs);
+
+
+	ar = RNGABSPTR(*regs);
 	memcpy(cmds, i8042_cmds, sizeof(i8042_cmds));
-	cmds[0].addr = (void *) &(((i8042_regs_t *) regs)->status);
-	cmds[3].addr = (void *) &(((i8042_regs_t *) regs)->data);
+	cmds[0].addr = (void *) &ar->status;
+	cmds[3].addr = (void *) &ar->data;
 
 	irq_code_t irq_code = {
Index: uspace/drv/char/i8042/i8042.h
===================================================================
--- uspace/drv/char/i8042/i8042.h	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/char/i8042/i8042.h	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -68,5 +68,5 @@
 } i8042_t;
 
-int i8042_init(i8042_t *, void *, size_t, int, int, ddf_dev_t *);
+int i8042_init(i8042_t *, addr_range_t *, int, int, ddf_dev_t *);
 
 #endif
Index: uspace/drv/char/i8042/main.c
===================================================================
--- uspace/drv/char/i8042/main.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/char/i8042/main.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -49,6 +49,5 @@
  *
  * @param[in]  dev            Device asking for the addresses.
- * @param[out] io_reg_address Base address of the memory range.
- * @param[out] io_reg_size    Size of the memory range.
+ * @param[out] p_io_reg       Pointer to register range.
  * @param[out] kbd_irq        Primary port IRQ.
  * @param[out] mouse_irq      Auxiliary port IRQ.
@@ -57,6 +56,6 @@
  *
  */
-static int get_my_registers(ddf_dev_t *dev, uintptr_t *io_reg_address,
-    size_t *io_reg_size, int *kbd_irq, int *mouse_irq)
+static int get_my_registers(ddf_dev_t *dev, addr_range_t *p_io_reg,
+    int *kbd_irq, int *mouse_irq)
 {
 	assert(dev);
@@ -79,9 +78,6 @@
 	}
 	
-	if (io_reg_address)
-		*io_reg_address = hw_resources.io_ranges.ranges[0].address;
-	
-	if (io_reg_size)
-		*io_reg_size = hw_resources.io_ranges.ranges[0].size;
+	if (p_io_reg)
+		*p_io_reg = hw_resources.io_ranges.ranges[0];
 	
 	if (kbd_irq)
@@ -104,6 +100,5 @@
 static int i8042_dev_add(ddf_dev_t *device)
 {
-	uintptr_t io_regs = 0;
-	size_t io_size = 0;
+	addr_range_t io_regs;
 	int kbd = 0;
 	int mouse = 0;
@@ -113,5 +108,5 @@
 		return EINVAL;
 	
-	rc = get_my_registers(device, &io_regs, &io_size, &kbd, &mouse);
+	rc = get_my_registers(device, &io_regs, &kbd, &mouse);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed to get registers: %s.",
@@ -120,6 +115,7 @@
 	}
 	
-	ddf_msg(LVL_DEBUG, "I/O regs at %p (size %zuB), IRQ kbd %d, IRQ mouse %d.",
-	    (void *) io_regs, io_size, kbd, mouse);
+	ddf_msg(LVL_DEBUG,
+	    "I/O regs at %p (size %zuB), IRQ kbd %d, IRQ mouse %d.",
+	    RNGABSPTR(io_regs), RNGSZ(io_regs), kbd, mouse);
 	
 	i8042_t *i8042 = ddf_dev_data_alloc(device, sizeof(i8042_t));
@@ -129,5 +125,5 @@
 	}
 	
-	rc = i8042_init(i8042, (void *) io_regs, io_size, kbd, mouse, device);
+	rc = i8042_init(i8042, &io_regs, kbd, mouse, device);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed to initialize i8042 driver: %s.",
Index: uspace/drv/infrastructure/rootmac/rootmac.c
===================================================================
--- uspace/drv/infrastructure/rootmac/rootmac.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/infrastructure/rootmac/rootmac.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -54,4 +54,5 @@
 			.address = 0xfec00000,
 			.size = 4,
+			.relative = false,
 			.endianness = LITTLE_ENDIAN
 		}
@@ -62,4 +63,5 @@
 			.address = 0xfee00000,
 			.size = 4,
+			.relative = false,
 			.endianness = LITTLE_ENDIAN
 		}
Index: uspace/drv/infrastructure/rootmalta/rootmalta.c
===================================================================
--- uspace/drv/infrastructure/rootmalta/rootmalta.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/infrastructure/rootmalta/rootmalta.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -99,4 +99,5 @@
 			.address = GT_BASE + GT_PCI_CONFADDR,
 			.size = 4,
+			.relative = false,
 			.endianness = LITTLE_ENDIAN
 		}
@@ -107,4 +108,5 @@
 			.address = GT_BASE + GT_PCI_CONFDATA,
 			.size = 4,
+			.relative = false,
 			.endianness = LITTLE_ENDIAN
 		}
Index: uspace/drv/infrastructure/rootpc/rootpc.c
===================================================================
--- uspace/drv/infrastructure/rootpc/rootpc.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/infrastructure/rootpc/rootpc.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -81,4 +81,5 @@
 			.address = 0xCF8,
 			.size = 4,
+			.relative = false,
 			.endianness = LITTLE_ENDIAN
 		}
@@ -89,4 +90,5 @@
 			.address = 0xCFC,
 			.size = 4,
+			.relative = false,
 			.endianness = LITTLE_ENDIAN
 		}
Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/nic/e1k/e1k.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -1941,5 +1941,5 @@
 	e1000->irq = hw_resources->irqs.irqs[0];
 	e1000->reg_base_phys =
-	    MEMADDR_TO_PTR(hw_resources->mem_ranges.ranges[0].address);
+	    MEMADDR_TO_PTR(RNGABS(hw_resources->mem_ranges.ranges[0]));
 	
 	return EOK;
Index: uspace/drv/nic/ne2k/ne2k.c
===================================================================
--- uspace/drv/nic/ne2k/ne2k.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -211,13 +211,12 @@
 	ne2k->irq = hw_res_parsed.irqs.irqs[0];
 	
-	ne2k->base_port = (void *) (uintptr_t)
-	    hw_res_parsed.io_ranges.ranges[0].address;
+	addr_range_t regs = hw_res_parsed.io_ranges.ranges[0];
+	ne2k->base_port = RNGABSPTR(regs);
 	
 	hw_res_list_parsed_clean(&hw_res_parsed);
 	
-	/* Enable port I/O */
-	if (pio_enable(ne2k->base_port, NE2K_IO_SIZE, &ne2k->port) != EOK)
+	/* Enable programmed I/O */
+	if (pio_enable_range(&regs, &ne2k->port) != EOK)
 		return EADDRNOTAVAIL;
-	
 	
 	ne2k->data_port = ne2k->port + NE2K_DATA;
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/drv/nic/rtl8139/driver.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -1087,5 +1087,5 @@
 	ddf_msg(LVL_DEBUG, "%s device: irq 0x%x assigned", ddf_dev_get_name(dev), rtl8139->irq);
 
-	rtl8139->io_addr = IOADDR_TO_PTR(hw_resources->io_ranges.ranges[0].address);
+	rtl8139->io_addr = IOADDR_TO_PTR(RNGABS(hw_resources->io_ranges.ranges[0]));
 	if (hw_resources->io_ranges.ranges[0].size < RTL8139_IO_SIZE) {
 		ddf_msg(LVL_ERROR, "i/o range assigned to the device "
Index: uspace/lib/c/generic/ddi.c
===================================================================
--- uspace/lib/c/generic/ddi.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/lib/c/generic/ddi.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -42,4 +42,7 @@
 #include <ddi.h>
 #include <libarch/ddi.h>
+#include <device/hw_res.h>
+#include <device/hw_res_parsed.h>
+#include <device/pio_window.h>
 #include <libc.h>
 #include <task.h>
@@ -134,4 +137,56 @@
 	
 	return __SYSCALL1(SYS_IOSPACE_ENABLE, (sysarg_t) &arg);
+}
+
+/** Enable PIO for specified address range.
+ *
+ * @param range I/O range to be enable.
+ * @param virt  Virtual address for application's PIO operations. 
+ */
+int pio_enable_range(addr_range_t *range, void **virt)
+{
+	return pio_enable(RNGABSPTR(*range), RNGSZ(*range), virt);
+}
+
+/** Enable PIO for specified HW resource wrt. to the PIO window.
+ *
+ * @param win      PIO window. May be NULL if the resources are known to be
+ *                 absolute.
+ * @param res      Resources specifying the I/O range wrt. to the PIO window.
+ * @param virt     Virtual address for application's PIO operations.
+ *
+ * @return EOK on success.
+ * @return Negative error code on failure.
+ *
+ */
+int pio_enable_resource(pio_window_t *win, hw_resource_t *res, void **virt)
+{
+	uintptr_t addr;
+	size_t size;
+
+	switch (res->type) {
+	case IO_RANGE:
+		addr = res->res.io_range.address;
+		if (res->res.io_range.relative) {
+			if (!win)
+				return EINVAL;
+			addr += win->io.base;
+		}
+		size = res->res.io_range.size;
+		break;
+	case MEM_RANGE:
+		addr = res->res.mem_range.address;
+		if (res->res.mem_range.relative) {
+			if (!win)
+				return EINVAL;
+			addr += win->mem.base;
+		}
+		size = res->res.mem_range.size;
+		break;
+	default:
+		return EINVAL;
+	}
+
+	return pio_enable((void *) addr, size, virt);	
 }
 
Index: uspace/lib/c/generic/device/hw_res_parsed.c
===================================================================
--- uspace/lib/c/generic/device/hw_res_parsed.c	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/lib/c/generic/device/hw_res_parsed.c	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -80,12 +80,36 @@
 }
 
+static uint64_t absolutize(uint64_t addr, bool relative, uint64_t base)
+{
+	if (!relative)
+		return addr;
+	else
+		return addr + base;
+}
+
+static uint64_t relativize(uint64_t addr, bool relative, uint64_t base)
+{
+	if (relative)
+		return addr;
+	else
+		return addr - base;
+}
+
 static void hw_res_parse_add_io_range(hw_res_list_parsed_t *out,
-    const hw_resource_t *res, int flags)
-{
+    const pio_window_t *win, const hw_resource_t *res, int flags)
+{
+	endianness_t endianness;
+	uint64_t absolute;
+	uint64_t relative;
+	size_t size;
+
 	assert(res && (res->type == IO_RANGE));
 	
-	uint64_t address = res->res.io_range.address;
-	endianness_t endianness = res->res.io_range.endianness;
-	size_t size = res->res.io_range.size;
+	absolute = absolutize(res->res.io_range.address,
+	    res->res.io_range.relative, win->io.base);
+	relative = relativize(res->res.io_range.address,
+	    res->res.io_range.relative, win->io.base);
+	size = res->res.io_range.size;
+	endianness = res->res.io_range.endianness;
 	
 	if ((size == 0) && (!(flags & HW_RES_KEEP_ZERO_AREA)))
@@ -97,26 +121,38 @@
 	if (!keep_duplicit) {
 		for (size_t i = 0; i < count; i++) {
-			uint64_t s_address = out->io_ranges.ranges[i].address;
-			size_t s_size = out->io_ranges.ranges[i].size;
+			uint64_t s_address;
+			size_t s_size;
+
+			s_address = RNGABS(out->io_ranges.ranges[i]);
+			s_size = RNGSZ(out->io_ranges.ranges[i]);
 			
-			if ((address == s_address) && (size == s_size))
-				return;
-		}
-	}
-	
-	out->io_ranges.ranges[count].address = address;
+			if ((absolute == s_address) && (size == s_size))
+				return;
+		}
+	}
+	
+	RNGABS(out->io_ranges.ranges[count]) = absolute;
+	RNGREL(out->io_ranges.ranges[count]) = relative;
+	RNGSZ(out->io_ranges.ranges[count]) = size;
 	out->io_ranges.ranges[count].endianness = endianness;
-	out->io_ranges.ranges[count].size = size;
 	out->io_ranges.count++;
 }
 
 static void hw_res_parse_add_mem_range(hw_res_list_parsed_t *out,
-    const hw_resource_t *res, int flags)
-{
+    const pio_window_t *win, const hw_resource_t *res, int flags)
+{
+	endianness_t endianness;
+	uint64_t absolute;
+	uint64_t relative;
+	size_t size;
+	
 	assert(res && (res->type == MEM_RANGE));
 	
-	uint64_t address = res->res.mem_range.address;
-	endianness_t endianness = res->res.mem_range.endianness;
-	size_t size = res->res.mem_range.size;
+	absolute = absolutize(res->res.mem_range.address,
+	    res->res.mem_range.relative, win->mem.base);
+	relative = relativize(res->res.mem_range.address,
+	    res->res.mem_range.relative, win->mem.base);
+	size = res->res.mem_range.size;
+	endianness = res->res.mem_range.endianness;
 	
 	if ((size == 0) && (!(flags & HW_RES_KEEP_ZERO_AREA)))
@@ -128,15 +164,19 @@
 	if (!keep_duplicit) {
 		for (size_t i = 0; i < count; ++i) {
-			uint64_t s_address = out->mem_ranges.ranges[i].address;
-			size_t s_size = out->mem_ranges.ranges[i].size;
+			uint64_t s_address;
+			size_t s_size;
+
+			s_address = RNGABS(out->mem_ranges.ranges[i]);;
+			s_size = RNGSZ(out->mem_ranges.ranges[i]);
 			
-			if ((address == s_address) && (size == s_size))
-				return;
-		}
-	}
-	
-	out->mem_ranges.ranges[count].address = address;
+			if ((absolute == s_address) && (size == s_size))
+				return;
+		}
+	}
+	
+	RNGABS(out->mem_ranges.ranges[count]) = absolute;
+	RNGREL(out->mem_ranges.ranges[count]) = relative;
+	RNGSZ(out->mem_ranges.ranges[count]) = size;
 	out->mem_ranges.ranges[count].endianness = endianness;
-	out->mem_ranges.ranges[count].size = size;
 	out->mem_ranges.count++;
 }
@@ -144,21 +184,21 @@
 /** Parse list of hardware resources
  *
- * @param      hw_resources Original structure resource
- * @param[out] out          Output parsed resources
- * @param      flags        Flags of the parsing.
- *                          HW_RES_KEEP_ZERO_AREA for keeping
- *                          zero-size areas, HW_RES_KEEP_DUPLICITIES
- *                          for keep duplicit areas
+ * @param      win          PIO window.
+ * @param      res          Original structure resource.
+ * @param[out] out          Output parsed resources.
+ * @param      flags        Flags of the parsing:
+ *                          HW_RES_KEEP_ZERO_AREA for keeping zero-size areas,
+ *                          HW_RES_KEEP_DUPLICITIES to keep duplicit areas.
  *
  * @return EOK if succeed, error code otherwise.
  *
  */
-int hw_res_list_parse(const hw_resource_list_t *hw_resources,
-    hw_res_list_parsed_t *out, int flags)
-{
-	if ((!hw_resources) || (!out))
+int hw_res_list_parse(const pio_window_t *win,
+    const hw_resource_list_t *res, hw_res_list_parsed_t *out, int flags)
+{
+	if (!res || !out)
 		return EINVAL;
 	
-	size_t res_count = hw_resources->count;
+	size_t res_count = res->count;
 	hw_res_list_parsed_clean(out);
 	
@@ -174,5 +214,5 @@
 	
 	for (size_t i = 0; i < res_count; ++i) {
-		const hw_resource_t *resource = &(hw_resources->resources[i]);
+		const hw_resource_t *resource = &res->resources[i];
 		
 		switch (resource->type) {
@@ -181,8 +221,8 @@
 			break;
 		case IO_RANGE:
-			hw_res_parse_add_io_range(out, resource, flags);
+			hw_res_parse_add_io_range(out, win, resource, flags);
 			break;
 		case MEM_RANGE:
-			hw_res_parse_add_mem_range(out, resource, flags);
+			hw_res_parse_add_mem_range(out, win, resource, flags);
 			break;
 		case DMA_CHANNEL_8:
@@ -216,4 +256,7 @@
     hw_res_list_parsed_t *hw_res_parsed, int flags)
 {
+	pio_window_t pio_window;
+	int rc;
+
 	if (!hw_res_parsed)
 		return EBADMEM;
@@ -222,10 +265,15 @@
 	hw_res_list_parsed_clean(hw_res_parsed);
 	memset(&hw_resources, 0, sizeof(hw_resource_list_t));
-	
-	int rc = hw_res_get_resource_list(sess, &hw_resources);
+
+	rc = pio_window_get(sess, &pio_window);
+	if (rc != EOK)
+		return rc; 
+	
+	rc = hw_res_get_resource_list(sess, &hw_resources);
 	if (rc != EOK)
 		return rc;
-	
-	rc = hw_res_list_parse(&hw_resources, hw_res_parsed, flags);
+
+	rc = hw_res_list_parse(&pio_window, &hw_resources, hw_res_parsed,
+	    flags);
 	hw_res_clean_resource_list(&hw_resources);
 	
Index: uspace/lib/c/include/ddi.h
===================================================================
--- uspace/lib/c/include/ddi.h	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/lib/c/include/ddi.h	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -40,4 +40,7 @@
 #include <sys/time.h>
 #include <abi/ddi/irq.h>
+#include <device/hw_res.h>
+#include <device/hw_res_parsed.h>
+#include <device/pio_window.h>
 #include <task.h>
 
@@ -55,4 +58,6 @@
 extern int dmamem_unmap_anonymous(void *);
 
+extern int pio_enable_range(addr_range_t *, void **);
+extern int pio_enable_resource(pio_window_t *, hw_resource_t *, void **);
 extern int pio_enable(void *, size_t, void **);
 
Index: uspace/lib/c/include/device/hw_res.h
===================================================================
--- uspace/lib/c/include/device/hw_res.h	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/lib/c/include/device/hw_res.h	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -76,12 +76,14 @@
 		struct {
 			uint64_t address;
+			size_t size;
+			bool relative;
 			endianness_t endianness;
-			size_t size;
 		} mem_range;
 		
 		struct {
 			uint64_t address;
+			size_t size;
+			bool relative;
 			endianness_t endianness;
-			size_t size;
 		} io_range;
 		
Index: uspace/lib/c/include/device/hw_res_parsed.h
===================================================================
--- uspace/lib/c/include/device/hw_res_parsed.h	(revision 695b6ff32cdb5ebb7fa100f5cba53b124a106990)
+++ uspace/lib/c/include/device/hw_res_parsed.h	(revision ddd0499d218f4fad4f9b6e819d50044f2863aba0)
@@ -37,4 +37,5 @@
 
 #include <device/hw_res.h>
+#include <device/pio_window.h>
 #include <str.h>
 
@@ -45,14 +46,28 @@
 #define HW_RES_KEEP_DUPLICIT   0x2
 
+
+#define RNGABS(rng)	(rng).address.absolute
+#define RNGREL(rng)	(rng).address.relative
+#define RNGSZ(rng)	(rng).size
+
+#define RNGABSPTR(rng)	((void *) ((uintptr_t) RNGABS((rng))))
+
+typedef struct address64 {
+	/** Aboslute address. */ 
+	uint64_t absolute;
+	/** PIO window base relative address. */
+	uint64_t relative; 
+} address64_t;
+
 /** Address range structure */
 typedef struct addr_range {
 	/** Start address */
-	uint64_t address;
-	
-	/** Endianness */
-	endianness_t endianness;
+	address64_t address;
 	
 	/** Area size */
 	size_t size;
+
+	/** Endianness */
+	endianness_t endianness;
 } addr_range_t;
 
@@ -139,5 +154,5 @@
 }
 
-extern int hw_res_list_parse(const hw_resource_list_t *,
+extern int hw_res_list_parse(const pio_window_t *, const hw_resource_list_t *,
     hw_res_list_parsed_t *, int);
 extern int hw_res_get_list_parsed(async_sess_t *, hw_res_list_parsed_t *, int);
