Index: uspace/lib/libc/arch/ia32/include/ddi.h
===================================================================
--- uspace/lib/libc/arch/ia32/include/ddi.h	(revision bc18d63b733703c3262a3a720f92513621962cff)
+++ uspace/lib/libc/arch/ia32/include/ddi.h	(revision 0d5a50cade5ee95d9afc0d055a94381254bb6e18)
@@ -33,4 +33,6 @@
 #ifndef LIBC_ia32_DDI_H_
 #define LIBC_ia32_DDI_H_
+
+#define IO_SPACE_BOUNDARY	((void *) (64 * 1024))
 
 static inline void outb(int16_t port, uint8_t b)
Index: uspace/lib/libc/generic/ddi.c
===================================================================
--- uspace/lib/libc/generic/ddi.c	(revision bc18d63b733703c3262a3a720f92513621962cff)
+++ uspace/lib/libc/generic/ddi.c	(revision 0d5a50cade5ee95d9afc0d055a94381254bb6e18)
@@ -36,4 +36,7 @@
 #include <libc.h>
 #include <task.h>
+#include <as.h>
+#include <align.h>
+#include <libarch/config.h>
 #include <kernel/ddi/ddi_arg.h>
 
@@ -42,16 +45,18 @@
  * Caller of this function must have the CAP_MEM_MANAGER capability.
  *
- * @param pf Physical address of the starting frame.
- * @param vp Virtual address of the sterting page.
- * @param pages Number of pages to map.
- * @param flags Flags for the new address space area.
+ * @param pf		Physical address of the starting frame.
+ * @param vp		Virtual address of the starting page.
+ * @param pages		Number of pages to map.
+ * @param flags		Flags for the new address space area.
  *
- * @return 0 on success, EPERM if the caller lacks the CAP_MEM_MANAGER capability,
- *	   ENOENT if there is no task with specified ID and ENOMEM if there
- *	   was some problem in creating address space area.
+ * @return 		0 on success, EPERM if the caller lacks the
+ *			CAP_MEM_MANAGER capability, ENOENT if there is no task
+ *			with specified ID and ENOMEM if there was some problem
+ *			in creating address space area.
  */
 int physmem_map(void *pf, void *vp, unsigned long pages, int flags)
 {
-	return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) pf, (sysarg_t) vp, pages, flags);
+	return __SYSCALL4(SYS_PHYSMEM_MAP, (sysarg_t) pf, (sysarg_t) vp, pages,
+	    flags);
 }
 
@@ -60,11 +65,12 @@
  * Caller of this function must have the IO_MEM_MANAGER capability.
  *
- * @param id Task ID.
- * @param ioaddr Starting address of the I/O range.
- * @param size Size of the range.
+ * @param id		Task ID.
+ * @param ioaddr	Starting address of the I/O range.
+ * @param size		Size of the range.
  *
- * @return 0 on success, EPERM if the caller lacks the CAP_IO_MANAGER capability,
- *	   ENOENT if there is no task with specified ID and ENOMEM if there
- *	   was some problem in allocating memory.
+ * @return		0 on success, EPERM if the caller lacks the
+ *			CAP_IO_MANAGER capability, ENOENT if there is no task
+ *			with specified ID and ENOMEM if there was some problem
+ *			in allocating memory.
  */
 int iospace_enable(task_id_t id, void *ioaddr, unsigned long size)
@@ -81,5 +87,5 @@
 /** Interrupt control
  *
- * @param enable 1 - enable interrupts, 0 - disable interrupts
+ * @param enable	1 - enable interrupts, 0 - disable interrupts
  */
 int preemption_control(int enable)
@@ -88,4 +94,35 @@
 }
 
+/** Enable PIO for specified I/O range.
+ *
+ * @param pio_addr	I/O start address.
+ * @param size		Size of the I/O region.
+ * @param use_addr	Address where the final address for application's PIO
+ * 			will be stored.
+ *
+ * @return		Zero on success or negative error code.
+ */
+int pio_enable(void *pio_addr, size_t size, void **use_addr)
+{
+	void *phys;
+	void *virt;
+	size_t offset;
+	unsigned int pages;
+
+#ifdef IO_SPACE_BOUNDARY
+	if (pio_addr < IO_SPACE_BOUNDARY) {
+		*use_addr = pio_addr;
+		return iospace_enable(task_get_id(), pio_addr, size);
+	}
+#endif
+
+	phys = ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
+	offset = pio_addr - phys;
+	pages = ALIGN_UP(offset + size, PAGE_SIZE) >> PAGE_WIDTH;
+	virt = as_get_mappable_page(pages);
+	*use_addr = virt + offset;
+	return physmem_map(phys, virt, pages, AS_AREA_READ | AS_AREA_WRITE);
+}
+
 /** @}
  */
Index: uspace/lib/libc/include/ddi.h
===================================================================
--- uspace/lib/libc/include/ddi.h	(revision bc18d63b733703c3262a3a720f92513621962cff)
+++ uspace/lib/libc/include/ddi.h	(revision 0d5a50cade5ee95d9afc0d055a94381254bb6e18)
@@ -38,7 +38,8 @@
 #include <task.h>
 
-extern int physmem_map(void *pf, void *vp, unsigned long pages, int flags);
-extern int iospace_enable(task_id_t id, void *ioaddr, unsigned long size);
-extern int preemption_control(int enable);
+extern int physmem_map(void *, void *, unsigned long, int);
+extern int iospace_enable(task_id_t, void *, unsigned long);
+extern int preemption_control(int);
+extern int pio_enable(void *, size_t, void **);
 
 #endif
