Index: kernel/generic/include/align.h
===================================================================
--- kernel/generic/include/align.h	(revision 5f0f29ce3c25993ee100bdb9354b66dc6b762ae7)
+++ kernel/generic/include/align.h	(revision e49e2348e7647a4dd4d4e2879082790396c4f4f3)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup generic	
+/** @addtogroup generic
  * @ingroup others
  * @{
@@ -33,5 +33,5 @@
 /**
  * @file
- * @brief	Macros for making values and addresses aligned.
+ * @brief Macros for making values and addresses aligned.
  */
 
@@ -44,5 +44,5 @@
  * @param a Size of alignment, must be power of 2.
  */
-#define ALIGN_DOWN(s, a)	((s) & ~((a) - 1))
+#define ALIGN_DOWN(s, a)  ((s) & ~((a) - 1))
 
 
@@ -52,5 +52,5 @@
  * @param a Size of alignment, must be power of 2.
  */
-#define ALIGN_UP(s, a)		(((s) + ((a) - 1)) & ~((a) - 1))
+#define ALIGN_UP(s, a)  (((s) + ((a) - 1)) & ~((a) - 1))
 
 #endif
Index: kernel/generic/include/mm/frame.h
===================================================================
--- kernel/generic/include/mm/frame.h	(revision 5f0f29ce3c25993ee100bdb9354b66dc6b762ae7)
+++ kernel/generic/include/mm/frame.h	(revision e49e2348e7647a4dd4d4e2879082790396c4f4f3)
@@ -40,4 +40,5 @@
 #include <adt/list.h>
 #include <mm/buddy.h>
+#include <synch/spinlock.h>
 #include <arch/mm/page.h>
 #include <arch/mm/frame.h>
@@ -68,12 +69,49 @@
 typedef uint8_t zone_flags_t;
 
+/** Available zone (free for allocation) */
+#define ZONE_AVAILABLE  0x00
 /** Zone is reserved (not available for allocation) */
-#define ZONE_RESERVED  0x08
+#define ZONE_RESERVED   0x08
 /** Zone is used by firmware (not available for allocation) */
-#define ZONE_FIRMWARE  0x10
+#define ZONE_FIRMWARE   0x10
 
 /** Currently there is no equivalent zone flags
     for frame flags */
 #define FRAME_TO_ZONE_FLAGS(frame_flags)  0
+
+typedef struct {
+	count_t refcount;     /**< Tracking of shared frames */
+	uint8_t buddy_order;  /**< Buddy system block order */
+	link_t buddy_link;    /**< Link to the next free block inside
+                               one order */
+	void *parent;         /**< If allocated by slab, this points there */
+} frame_t;
+
+typedef struct {
+	pfn_t base;                    /**< Frame_no of the first frame
+                                        in the frames array */
+	count_t count;                 /**< Size of zone */
+	count_t free_count;            /**< Number of free frame_t
+                                        structures */
+	count_t busy_count;            /**< Number of busy frame_t
+                                        structures */
+	zone_flags_t flags;            /**< Type of the zone */
+	
+	frame_t *frames;               /**< Array of frame_t structures
+                                        in this zone */
+	buddy_system_t *buddy_system;  /**< Buddy system for the zone */
+} zone_t;
+
+/*
+ * The zoneinfo.lock must be locked when accessing zoneinfo structure.
+ * Some of the attributes in zone_t structures are 'read-only'
+ */
+typedef struct {
+	SPINLOCK_DECLARE(lock);
+	count_t count;
+	zone_t info[ZONES_MAX];
+} zones_t;
+
+extern zones_t zones;
 
 static inline uintptr_t PFN2ADDR(pfn_t frame)
@@ -99,4 +137,9 @@
 }
 
+static inline bool zone_flags_available(zone_flags_t flags)
+{
+	return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0);
+}
+
 #define IS_BUDDY_ORDER_OK(index, order) \
     ((~(((unative_t) -1) << (order)) & (index)) == 0)
@@ -118,4 +161,5 @@
 extern void frame_reference_add(pfn_t);
 
+extern count_t find_zone(pfn_t frame, count_t count, count_t hint);
 extern count_t zone_create(pfn_t, count_t, pfn_t, zone_flags_t);
 extern void *frame_get_parent(pfn_t, count_t);
Index: kernel/generic/include/mm/page.h
===================================================================
--- kernel/generic/include/mm/page.h	(revision 5f0f29ce3c25993ee100bdb9354b66dc6b762ae7)
+++ kernel/generic/include/mm/page.h	(revision e49e2348e7647a4dd4d4e2879082790396c4f4f3)
@@ -62,5 +62,4 @@
 
 extern uintptr_t hw_map(uintptr_t physaddr, size_t size);
-extern void hw_area(void);
 
 #endif
Index: kernel/generic/src/ddi/ddi.c
===================================================================
--- kernel/generic/src/ddi/ddi.c	(revision 5f0f29ce3c25993ee100bdb9354b66dc6b762ae7)
+++ kernel/generic/src/ddi/ddi.c	(revision e49e2348e7647a4dd4d4e2879082790396c4f4f3)
@@ -30,8 +30,8 @@
  * @{
  */
- 
+
 /**
  * @file
- * @brief	Device Driver Interface functions.
+ * @brief Device Driver Interface functions.
  *
  * This file contains functions that comprise the Device Driver Interface.
@@ -48,5 +48,5 @@
 #include <synch/spinlock.h>
 #include <syscall/copy.h>
-#include <adt/list.h>
+#include <adt/btree.h>
 #include <arch.h>
 #include <align.h>
@@ -56,11 +56,11 @@
 SPINLOCK_INITIALIZE(parea_lock);
 
-/** List with enabled physical memory areas. */
-static LIST_INITIALIZE(parea_head);
+/** B+tree with enabled physical memory areas. */
+static btree_t parea_btree;
 
 /** Initialize DDI. */
 void ddi_init(void)
 {
-	hw_area();
+	btree_create(&parea_btree);
 }
 
@@ -69,20 +69,14 @@
  * @param parea Pointer to physical area structure.
  *
- * @todo This function doesn't check for overlaps. It depends on the kernel to
- * create disjunct physical memory areas.
  */
 void ddi_parea_register(parea_t *parea)
 {
-	ipl_t ipl;
-	
-	ipl = interrupts_disable();
+	ipl_t ipl = interrupts_disable();
 	spinlock_lock(&parea_lock);
 	
 	/*
-	 * TODO: we should really check for overlaps here.
-	 * However, we should be safe because the kernel is pretty sane.
-	 */
-	link_initialize(&parea->link);
-	list_append(&parea->link, &parea_head);
+	 * We don't check for overlaps here as the kernel is pretty sane.
+	 */
+	btree_insert(&parea_btree, (btree_key_t) parea->pbase, parea, NULL);
 	
 	spinlock_unlock(&parea_lock);
@@ -92,62 +86,81 @@
 /** Map piece of physical memory into virtual address space of current task.
  *
- * @param pf Physical address of the starting frame.
- * @param vp Virtual address of the starting page.
+ * @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 Address space area flags for the mapping.
  *
  * @return 0 on success, EPERM if the caller lacks capabilities to use this
- *  syscall, ENOENT if there is no task matching the specified ID or the
- *  physical address space is not enabled for mapping and ENOMEM if there
- *  was a problem in creating address space area.
- */
-static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, pfn_t pages, int flags)
-{
-	ipl_t ipl;
-	cap_t caps;
+ *         syscall, EBADMEM if pf or vf is not page aligned, ENOENT if there
+ *         is no task matching the specified ID or the physical address space
+ *         is not enabled for mapping and ENOMEM if there was a problem in
+ *         creating address space area.
+ *
+ */
+static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, count_t pages, int flags)
+{
+	ASSERT(TASK);
+	ASSERT((pf % FRAME_SIZE) == 0);
+	ASSERT((vp % PAGE_SIZE) == 0);
+	
+	/*
+	 * Make sure the caller is authorised to make this syscall.
+	 */
+	cap_t caps = cap_get(TASK);
+	if (!(caps & CAP_MEM_MANAGER))
+		return EPERM;
+	
 	mem_backend_data_t backend_data;
-	
 	backend_data.base = pf;
 	backend_data.frames = pages;
 	
-	/*
-	 * Make sure the caller is authorised to make this syscall.
-	 */
-	caps = cap_get(TASK);
-	if (!(caps & CAP_MEM_MANAGER))
-		return EPERM;
-	
-	ipl = interrupts_disable();
-	
-	/*
-	 * Check if the physical memory area is enabled for mapping.
-	 */
-	spinlock_lock(&parea_lock);
-	
-	bool fnd = false;
-	link_t *cur;
-	
-	for (cur = parea_head.next; cur != &parea_head; cur = cur->next) {
-		parea_t *parea = list_get_instance(cur, parea_t, link);
-		if ((parea->pbase <= pf) && (ADDR2PFN(pf - parea->pbase) + pages <= parea->frames)) {
-			fnd = true;
-			break;
-		}
-	}
-	
-	spinlock_unlock(&parea_lock);
-	
-	if (!fnd) {
-		/*
-		 * Physical memory area cannot be mapped.
-		 */
-		interrupts_restore(ipl);
-		return ENOENT;
-	}
-	
+	ipl_t ipl = interrupts_disable();
+	
+	/* Find the zone of the physical memory */
+	spinlock_lock(&zones.lock);
+	count_t znum = find_zone(ADDR2PFN(pf), pages, 0);
+	
+	if (znum == (count_t) -1) {
+		/* Frames not found in any zones
+		 * -> assume it is hardware device and allow mapping
+		 */
+		spinlock_unlock(&zones.lock);
+		goto map;
+	}
+	
+	if (zones.info[znum].flags & ZONE_FIRMWARE) {
+		/* Frames are part of firmware */
+		spinlock_unlock(&zones.lock);
+		goto map;
+	}
+	
+	if (zone_flags_available(zones.info[znum].flags)) {
+		/* Frames are part of physical memory, check if the memory
+		 * region is enabled for mapping.
+		 */
+		spinlock_unlock(&zones.lock);
+		
+		spinlock_lock(&parea_lock);
+		btree_node_t *nodep;
+		parea_t *parea = (parea_t *) btree_search(&parea_btree,
+		    (btree_key_t) pf, &nodep);
+		
+		if ((!parea) || (parea->frames < pages))
+			goto err;
+		
+		spinlock_unlock(&parea_lock);
+		goto map;
+	}
+	
+err:
+	spinlock_unlock(&zones.lock);
+	interrupts_restore(ipl);
+	return ENOENT;
+	
+map:
 	spinlock_lock(&TASK->lock);
 	
-	if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp, AS_AREA_ATTR_NONE,
-		&phys_backend, &backend_data)) {
+	if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp,
+	    AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) {
 		/*
 		 * The address space area could not have been created.
@@ -175,26 +188,22 @@
  *
  * @return 0 on success, EPERM if the caller lacks capabilities to use this
- * 	syscall, ENOENT if there is no task matching the specified ID.
+ *           syscall, ENOENT if there is no task matching the specified ID.
+ *
  */
 static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size)
 {
-	ipl_t ipl;
-	cap_t caps;
-	task_t *t;
-	int rc;
-	
 	/*
 	 * Make sure the caller is authorised to make this syscall.
 	 */
-	caps = cap_get(TASK);
+	cap_t caps = cap_get(TASK);
 	if (!(caps & CAP_IO_MANAGER))
 		return EPERM;
 	
-	ipl = interrupts_disable();
+	ipl_t ipl = interrupts_disable();
 	spinlock_lock(&tasks_lock);
 	
-	t = task_find_by_id(id);
-	
-	if ((!t) || (!context_check(CONTEXT, t->context))) {
+	task_t *task = task_find_by_id(id);
+	
+	if ((!task) || (!context_check(CONTEXT, task->context))) {
 		/*
 		 * There is no task with the specified ID
@@ -206,13 +215,14 @@
 		return ENOENT;
 	}
-
+	
 	/* Lock the task and release the lock protecting tasks_btree. */
-	spinlock_lock(&t->lock);
+	spinlock_lock(&task->lock);
 	spinlock_unlock(&tasks_lock);
-
-	rc = ddi_iospace_enable_arch(t, ioaddr, size);
-	
-	spinlock_unlock(&t->lock);
-	interrupts_restore(ipl);
+	
+	int rc = ddi_iospace_enable_arch(task, ioaddr, size);
+	
+	spinlock_unlock(&task->lock);
+	interrupts_restore(ipl);
+	
 	return rc;
 }
@@ -226,5 +236,6 @@
  *
  * @return 0 on success, otherwise it returns error code found in errno.h
- */ 
+ *
+ */
 unative_t sys_physmem_map(unative_t phys_base, unative_t virt_base,
     unative_t pages, unative_t flags)
@@ -232,5 +243,5 @@
 	return (unative_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base,
 	    FRAME_SIZE), ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE),
-	    (pfn_t) pages, (int) flags);
+	    (count_t) pages, (int) flags);
 }
 
@@ -240,14 +251,13 @@
  *
  * @return 0 on success, otherwise it returns error code found in errno.h
- */ 
+ *
+ */
 unative_t sys_iospace_enable(ddi_ioarg_t *uspace_io_arg)
 {
 	ddi_ioarg_t arg;
-	int rc;
-	
-	rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
+	int rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
 	if (rc != 0)
 		return (unative_t) rc;
-		
+	
 	return (unative_t) ddi_iospace_enable((task_id_t) arg.task_id,
 	    (uintptr_t) arg.ioaddr, (size_t) arg.size);
@@ -257,17 +267,21 @@
  *
  * @param enable If non-zero, the preemption counter will be decremented,
- * 	leading to potential enabling of preemption. Otherwise the preemption
- * 	counter will be incremented, preventing preemption from occurring.
+ *               leading to potential enabling of preemption. Otherwise
+ *               the preemption counter will be incremented, preventing
+ *               preemption from occurring.
  *
  * @return Zero on success or EPERM if callers capabilities are not sufficient.
- */ 
+ *
+ */
 unative_t sys_preempt_control(int enable)
 {
 	if (!cap_get(TASK) & CAP_PREEMPT_CONTROL)
 		return EPERM;
+	
 	if (enable)
 		preemption_enable();
 	else
 		preemption_disable();
+	
 	return 0;
 }
Index: kernel/generic/src/mm/frame.c
===================================================================
--- kernel/generic/src/mm/frame.c	(revision 5f0f29ce3c25993ee100bdb9354b66dc6b762ae7)
+++ kernel/generic/src/mm/frame.c	(revision e49e2348e7647a4dd4d4e2879082790396c4f4f3)
@@ -49,5 +49,4 @@
 #include <debug.h>
 #include <adt/list.h>
-#include <synch/spinlock.h>
 #include <synch/mutex.h>
 #include <synch/condvar.h>
@@ -61,38 +60,5 @@
 #include <config.h>
 
-typedef struct {
-	count_t refcount;     /**< Tracking of shared frames */
-	uint8_t buddy_order;  /**< Buddy system block order */
-	link_t buddy_link;    /**< Link to the next free block inside
-                               one order */
-	void *parent;         /**< If allocated by slab, this points there */
-} frame_t;
-
-typedef struct {
-	pfn_t base;                    /**< Frame_no of the first frame
-                                        in the frames array */
-	count_t count;                 /**< Size of zone */
-	count_t free_count;            /**< Number of free frame_t
-                                        structures */
-	count_t busy_count;            /**< Number of busy frame_t
-                                        structures */
-	zone_flags_t flags;            /**< Type of the zone */
-	
-	frame_t *frames;               /**< Array of frame_t structures
-                                        in this zone */
-	buddy_system_t *buddy_system;  /**< Buddy system for the zone */
-} zone_t;
-
-/*
- * The zoneinfo.lock must be locked when accessing zoneinfo structure.
- * Some of the attributes in zone_t structures are 'read-only'
- */
-typedef struct {
-	SPINLOCK_DECLARE(lock);
-	count_t count;
-	zone_t info[ZONES_MAX];
-} zones_t;
-
-static zones_t zones;
+zones_t zones;
 
 /*
@@ -127,9 +93,4 @@
 {
 	return (frame - zone->frames);
-}
-
-static inline bool zone_flags_available(zone_flags_t flags)
-{
-	return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0);
 }
 
@@ -181,6 +142,9 @@
 	/* Move other zones up */
 	count_t j;
-	for (j = i; j < zones.count; j++)
-		zones.info[j + 1] = zones.info[j];
+	for (j = zones.count; j > i; j--) {
+		zones.info[j] = zones.info[j - 1];
+		zones.info[j].buddy_system->data =
+		    (void *) &zones.info[j - 1];
+	}
 	
 	zones.count++;
@@ -207,5 +171,5 @@
 }
 
-/** Find a zone with a given frame.
+/** Find a zone with a given frames.
  *
  * Assume interrupts are disabled and zones lock is
@@ -213,4 +177,5 @@
  *
  * @param frame Frame number contained in zone.
+ * @param count Number of frames to look for.
  * @param hint  Used as zone hint.
  *
@@ -218,5 +183,5 @@
  *
  */
-static count_t find_zone(pfn_t frame, count_t hint)
+count_t find_zone(pfn_t frame, count_t count, count_t hint)
 {
 	if (hint >= zones.count)
@@ -226,5 +191,5 @@
 	do {
 		if ((zones.info[i].base <= frame)
-		    && (zones.info[i].base + zones.info[i].count > frame))
+		    && (zones.info[i].base + zones.info[i].count >= frame + count))
 			return i;
 		
@@ -766,8 +731,12 @@
 	    zones.info[z2].count);
 	
-	/* Shift existing zones */
+	/* Move zones down */
 	count_t i;
-	for (i = z2 + 1; i < zones.count; i++)
+	for (i = z2 + 1; i < zones.count; i++) {
 		zones.info[i - 1] = zones.info[i];
+		zones.info[i - 1].buddy_system->data =
+		    (void *) &zones.info[i - 1];
+	}
+	
 	zones.count--;
 	
@@ -965,5 +934,5 @@
 	spinlock_lock(&zones.lock);
 	
-	count_t znum = find_zone(pfn, hint);
+	count_t znum = find_zone(pfn, 1, hint);
 	
 	ASSERT(znum != (count_t) -1);
@@ -981,5 +950,5 @@
 	spinlock_lock(&zones.lock);
 	
-	count_t znum = find_zone(pfn, hint);
+	count_t znum = find_zone(pfn, 1, hint);
 	
 	ASSERT(znum != (count_t) -1);
@@ -1112,5 +1081,5 @@
 	 */
 	pfn_t pfn = ADDR2PFN(frame);
-	count_t znum = find_zone(pfn, NULL);
+	count_t znum = find_zone(pfn, 1, NULL);
 	
 	ASSERT(znum != (count_t) -1);
@@ -1151,5 +1120,5 @@
 	 * First, find host frame zone for addr.
 	 */
-	count_t znum = find_zone(pfn, NULL);
+	count_t znum = find_zone(pfn, 1, NULL);
 	
 	ASSERT(znum != (count_t) -1);
@@ -1169,5 +1138,5 @@
 	count_t i;
 	for (i = 0; i < count; i++) {
-		count_t znum = find_zone(start + i, 0);
+		count_t znum = find_zone(start + i, 1, 0);
 		if (znum == (count_t) -1)  /* PFN not found */
 			continue;
@@ -1238,11 +1207,11 @@
 {
 #ifdef __32_BITS__
-	printf("#  base address flags    free frames  busy frames\n");
-	printf("-- ------------ -------- ------------ ------------\n");
+	printf("#  base address frames       flags    free frames  busy frames\n");
+	printf("-- ------------ ------------ -------- ------------ ------------\n");
 #endif
 
 #ifdef __64_BITS__
-	printf("#  base address         flags    free frames  busy frames\n");
-	printf("-- -------------------- -------- ------------ ------------\n");
+	printf("#  base address          frames      flags    free frames  busy frames\n");
+	printf("-- -------------------- ------------ -------- ------------ ------------\n");
 #endif
 	
@@ -1270,4 +1239,5 @@
 		
 		uintptr_t base = PFN2ADDR(zones.info[i].base);
+		count_t count = zones.info[i].count;
 		zone_flags_t flags = zones.info[i].flags;
 		count_t free_count = zones.info[i].free_count;
@@ -1279,21 +1249,23 @@
 		bool available = zone_flags_available(flags);
 		
+		printf("%-2" PRIc, i);
+		
 #ifdef __32_BITS__
-		printf("%-2" PRIc "   %10p %c%c%c      ", i, base,
+		printf("   %10p", base);
+#endif
+		
+#ifdef __64_BITS__
+		printf("   %18p", base);
+#endif
+		
+		printf(" %12" PRIc " %c%c%c      ", count,
 		    available ? 'A' : ' ',
 		    (flags & ZONE_RESERVED) ? 'R' : ' ',
 		    (flags & ZONE_FIRMWARE) ? 'F' : ' ');
-#endif
-		
-#ifdef __64_BITS__
-		printf("%-2" PRIc "   %18p %c%c%c      ", i, base,
-		    available ? 'A' : ' ',
-		    (flags & ZONE_RESERVED) ? 'R' : ' ',
-		    (flags & ZONE_FIRMWARE) ? 'F' : ' ');
-#endif
 		
 		if (available)
 			printf("%12" PRIc " %12" PRIc,
 			    free_count, busy_count);
+		
 		printf("\n");
 	}
