Index: arch/amd64/src/mm/page.c
===================================================================
--- arch/amd64/src/mm/page.c	(revision fcacfb74181dda313fd3d2c659cf9536f9e55ebc)
+++ arch/amd64/src/mm/page.c	(revision 84dd253c8c662703845d21109af33b9cc66c1854)
@@ -53,5 +53,5 @@
 		 * PA2KA(identity) mapping for all frames.
 		 */
-		for (i = 0; i < frames; i++) {
+		for (i = 0; i < config.memory_size/FRAME_SIZE; i++) {
 			map_page_to_frame(PA2KA(i * PAGE_SIZE), i * PAGE_SIZE, PAGE_CACHEABLE | PAGE_EXEC, KA2PA(dba));
 		}
Index: arch/ia32/src/mm/frame.c
===================================================================
--- arch/ia32/src/mm/frame.c	(revision fcacfb74181dda313fd3d2c659cf9536f9e55ebc)
+++ arch/ia32/src/mm/frame.c	(revision 84dd253c8c662703845d21109af33b9cc66c1854)
@@ -33,4 +33,5 @@
 #include <arch/boot/boot.h>
 #include <arch/boot/memmap.h>
+#include <panic.h>
 
 size_t hardcoded_unmapped_ktext_size = 0;
@@ -39,22 +40,22 @@
 void frame_arch_init(void)
 {
+	zone_t *z;
 	__u8 i;
 	
 	if (config.cpu_active == 1) {
-		/* Reserve the NULL frame */
-		frame_not_free(0x0);
+		for (i=e820counter;i>0;i--) {
+			if (e820table[i-1].type==MEMMAP_MEMORY_AVAILABLE) {
+				z = zone_create(e820table[i-1].base_address, e820table[i-1].size & ~(FRAME_SIZE-1), 0);
+				if (!z) {
+					panic("Cannot allocate zone (%dB).\n", e820table[i-1].size & ~(FRAME_SIZE-1));
+				}
+				zone_attach(z);
+			}
+		}
 		
-		/* Reserve well-known memory regions */
-		frame_region_not_free(0xa0000,0xff000);
-		frame_region_not_free(0xfec00000,0xffffffff);
-		
+		frame_not_free(0);
+
 		/* Reserve real mode bootstrap memory */
-		frame_region_not_free(BOOTSTRAP_OFFSET, BOOTSTRAP_OFFSET + hardcoded_unmapped_ktext_size + hardcoded_unmapped_kdata_size);
-		
-		for (i=e820counter;i>0;i--) {
-			if (e820table[i-1].type!=MEMMAP_MEMORY_AVAILABLE) {
-					frame_region_not_free(e820table[i-1].base_address, e820table[i-1].base_address+e820table[i-1].size);
-				}
-			}
+                frame_region_not_free(BOOTSTRAP_OFFSET, BOOTSTRAP_OFFSET + hardcoded_unmapped_ktext_size + hardcoded_unmapped_kdata_size);
 	}
 }
Index: arch/ia32/src/mm/page.c
===================================================================
--- arch/ia32/src/mm/page.c	(revision fcacfb74181dda313fd3d2c659cf9536f9e55ebc)
+++ arch/ia32/src/mm/page.c	(revision 84dd253c8c662703845d21109af33b9cc66c1854)
@@ -56,5 +56,5 @@
 		 * PA2KA(identity) mapping for all frames.
 		 */
-		for (i = 0; i < frames; i++)
+		for (i = 0; i < config.memory_size/PAGE_SIZE; i++)
 			map_page_to_frame(PA2KA(i * PAGE_SIZE), i * PAGE_SIZE, PAGE_CACHEABLE, KA2PA(dba));
 
Index: arch/ia32/src/smp/mps.c
===================================================================
--- arch/ia32/src/smp/mps.c	(revision fcacfb74181dda313fd3d2c659cf9536f9e55ebc)
+++ arch/ia32/src/smp/mps.c	(revision 84dd253c8c662703845d21109af33b9cc66c1854)
@@ -188,6 +188,4 @@
 	printf("%P: MPS Floating Pointer Structure\n", fs);
 
-	frame_not_free((__address) fs);
-
 	if (fs->config_type == 0 && fs->configuration_table) {
 		if (fs->mpfib2 >> 7) {
@@ -197,5 +195,4 @@
 
 		ct = (struct mps_ct *)PA2KA((__address)fs->configuration_table);
-		frame_not_free((__address) ct);
 		config.cpu_count = configure_via_ct();
 	} 
Index: arch/ia64/Makefile.inc
===================================================================
--- arch/ia64/Makefile.inc	(revision fcacfb74181dda313fd3d2c659cf9536f9e55ebc)
+++ arch/ia64/Makefile.inc	(revision 84dd253c8c662703845d21109af33b9cc66c1854)
@@ -33,3 +33,4 @@
 	arch/ivt.S \
 	arch/interrupt_handler.c \
-	arch/fmath.c
+	arch/fmath.c \
+	arch/mm/frame.c
Index: arch/ia64/src/dummy.s
===================================================================
--- arch/ia64/src/dummy.s	(revision fcacfb74181dda313fd3d2c659cf9536f9e55ebc)
+++ arch/ia64/src/dummy.s	(revision 84dd253c8c662703845d21109af33b9cc66c1854)
@@ -41,5 +41,4 @@
 .global cpu_priority_restore
 .global cpu_sleep
-.global frame_arch_init
 .global dummy
 .global fpu_enable
@@ -59,5 +58,4 @@
 cpu_priority_restore:
 cpu_sleep:
-frame_arch_init:
 fpu_init:
 fpu_enable:
Index: arch/ia64/src/mm/frame.c
===================================================================
--- arch/ia64/src/mm/frame.c	(revision 84dd253c8c662703845d21109af33b9cc66c1854)
+++ arch/ia64/src/mm/frame.c	(revision 84dd253c8c662703845d21109af33b9cc66c1854)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch/mm/frame.h>
+#include <mm/frame.h>
+#include <config.h>
+#include <panic.h>
+
+void frame_arch_init(void)
+{
+	zone_t *z;
+	
+	z = zone_create(0, config.memory_size, 0);
+	if (!z) {
+		panic("Can't allocate zone (%dB).\n", config.memory_size);
+	}
+	zone_attach(z);
+}
Index: arch/mips32/src/mm/frame.c
===================================================================
--- arch/mips32/src/mm/frame.c	(revision fcacfb74181dda313fd3d2c659cf9536f9e55ebc)
+++ arch/mips32/src/mm/frame.c	(revision 84dd253c8c662703845d21109af33b9cc66c1854)
@@ -31,7 +31,17 @@
 #include <arch/asm/boot.h>
 #include <arch/mm/page.h>
+#include <config.h>
+#include <panic.h>
 
 void frame_arch_init(void)
 {
+	zone_t *z;
+	
+	z = zone_create(0, config.memory_size, 0);
+	if (!z) {
+		panic("Can't allocate zone (%dB).\n", config.memory_size);
+	}
+	zone_attach(z);
+
 	/* Disable Everything until load address */
 	frame_region_not_free(0, KA2PA(KERNEL_LOAD_ADDRESS));
Index: arch/ppc32/src/mm/frame.c
===================================================================
--- arch/ppc32/src/mm/frame.c	(revision fcacfb74181dda313fd3d2c659cf9536f9e55ebc)
+++ arch/ppc32/src/mm/frame.c	(revision 84dd253c8c662703845d21109af33b9cc66c1854)
@@ -29,6 +29,15 @@
 #include <arch/mm/frame.h>
 #include <mm/frame.h>
+#include <config.h>
+#include <panic.h>
 
 void frame_arch_init(void)
 {
+        zone_t *z;
+
+        z = zone_create(0, config.memory_size & ~(FRAME_SIZE-1), 0);
+        if (!z) {
+                panic("Can't allocate zone (%dB).\n", config.memory_size & ~(FRAME_SIZE-1));
+        }
+        zone_attach(z);
 }
Index: include/mm/frame.h
===================================================================
--- include/mm/frame.h	(revision fcacfb74181dda313fd3d2c659cf9536f9e55ebc)
+++ include/mm/frame.h	(revision 84dd253c8c662703845d21109af33b9cc66c1854)
@@ -52,5 +52,4 @@
 
 struct frame {
-	zone_t *zone;		/**< host zone */
 	count_t refcount;	/**< when > 0, the frame is in busy list, otherwise the frame is in free list */
 	link_t link;		/**< link either to frame_zone free or busy list */
@@ -60,17 +59,10 @@
 extern link_t zone_head;		/**< list of all zones in the system */
 
-extern count_t frames;
-extern count_t frames_free;
-
-extern count_t kernel_frames;
-extern count_t kernel_frames_free;
-
-extern __u8 *frame_bitmap;
-extern count_t frame_bitmap_octets;
-
-extern __u8 *frame_kernel_bitmap;
+extern void zone_init(void);
+extern zone_t *zone_create(__address start, size_t size, int flags);
+extern void zone_attach(zone_t *zone);
 
 extern void frame_init(void);
-
+extern void frame_initialize(frame_t *frame, zone_t *zone);
 __address frame_alloc(int flags);
 extern void frame_free(__address addr);
@@ -78,19 +70,7 @@
 extern void frame_region_not_free(__address start, __address stop);
 
-extern void zone_init(void);
-extern zone_t *zone_create(__address start, size_t size, int flags);
-extern void zone_attach(zone_t *zone);
-
-extern void frame_initialize(frame_t *frame, zone_t *zone);
-extern __address frame_get_address(frame_t *frame);
-
 /*
  * TODO: Implement the following functions.
  */
-
-/*
-extern frame_t *frame_alloc(int flags);
-extern void frame_free(frame_t *frame);
-*/
 extern frame_t *frame_reference(frame_t *frame);
 extern void frame_release(frame_t *frame);
Index: src/mm/frame.c
===================================================================
--- src/mm/frame.c	(revision fcacfb74181dda313fd3d2c659cf9536f9e55ebc)
+++ src/mm/frame.c	(revision 84dd253c8c662703845d21109af33b9cc66c1854)
@@ -27,182 +27,247 @@
  */
 
+#include <typedefs.h>
 #include <arch/types.h>
-#include <func.h>
-
 #include <mm/heap.h>
 #include <mm/frame.h>
-#include <mm/page.h>
 #include <mm/vm.h>
-#include <arch/mm/page.h>
-
-#include <config.h>
-#include <memstr.h>
-
 #include <panic.h>
 #include <debug.h>
-
+#include <list.h>
 #include <synch/spinlock.h>
-
 #include <arch/asm.h>
 #include <arch.h>
 
-count_t frames = 0;
-count_t frames_free;
-
-__u8 *frame_bitmap;
-count_t frame_bitmap_octets;
-
-static spinlock_t framelock;
-
 spinlock_t zone_head_lock;       /**< this lock protects zone_head list */
 link_t zone_head;                /**< list of all zones in the system */
 
-
+/** Initialize physical memory management
+ *
+ * Initialize physical memory managemnt.
+ */
 void frame_init(void)
 {
 	if (config.cpu_active == 1) {
 		zone_init();
-
-		/*
-		 * The bootstrap processor will allocate all necessary memory for frame allocation.
-		 */
-
-		frames = config.memory_size / FRAME_SIZE;
-		frame_bitmap_octets = frames / 8 + (frames % 8 > 0);
-		frame_bitmap = (__u8 *) malloc(frame_bitmap_octets);
-		if (!frame_bitmap)
-			panic("malloc/frame_bitmap\n");
-
-		/*
-		 * Mark all frames free.
-		 */
-		memsetb((__address) frame_bitmap, frame_bitmap_octets, 0);
-		frames_free = frames;
-	}
-
-	/*
-	 * No frame allocations/reservations prior this point.
-	 */
+	}
 
 	frame_arch_init();
-
+	
 	if (config.cpu_active == 1) {
-		/*
-		 * Create the memory address space map. Marked frames and frame
-		 * regions cannot be used for allocation.
-		 */
-		frame_region_not_free(config.base, config.base + config.kernel_size);
-	}
-}
-
-/*
- * Allocate a frame.
+                frame_region_not_free(config.base, config.base + config.kernel_size + CONFIG_STACK_SIZE);
+        }	
+}
+
+/** Allocate a frame
+ *
+ * Allocate a frame of physical memory.
+ *
+ * @param flags Flags for host zone selection and address processing.
+ *
+ * @return Allocated frame.
  */
 __address frame_alloc(int flags)
 {
-	int i;
 	pri_t pri;
+	link_t *cur, *tmp;
+	zone_t *z;
+	zone_t *zone = NULL;
+	frame_t *frame = NULL;
+	__address v;
 	
 loop:
 	pri = cpu_priority_high();
-	spinlock_lock(&framelock);
-	if (frames_free) {
-		for (i=0; i < frames; i++) {
-			int m, n;
-		
-			m = i / 8;
-			n = i % 8;
-
-			if ((frame_bitmap[m] & (1<<n)) == 0) {
-				frame_bitmap[m] |= (1<<n);
-				frames_free--;
-				spinlock_unlock(&framelock);
-				cpu_priority_restore(pri);
-				if (flags & FRAME_KA) return PA2KA(i*FRAME_SIZE);
-				return i*FRAME_SIZE;
-			}
-		}
-		panic("frames_free inconsistent (%d)\n", frames_free);
-	}
-	spinlock_unlock(&framelock);
+	spinlock_lock(&zone_head_lock);
+	
+	/*
+	 * First, find suitable frame zone.
+	 */
+	for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
+		z = list_get_instance(cur, zone_t, link);
+		
+		spinlock_lock(&z->lock);
+		/*
+		 * Check if the zone has any free frames.
+		 */
+		if (z->free_count) {
+			zone = z;
+			break;
+		}
+		spinlock_unlock(&z->lock);
+	}
+	
+	if (!zone) {
+		if (flags & FRAME_PANIC)
+			panic("Can't allocate frame.\n");
+		
+		/*
+		 * TODO: Sleep until frames are available again.
+		 */
+		spinlock_unlock(&zone_head_lock);
+		cpu_priority_restore(pri);
+
+		panic("Sleep not implemented.\n");
+		goto loop;
+	}
+		
+	tmp = zone->free_head.next;
+	frame = list_get_instance(tmp, frame_t, link);
+
+	frame->refcount++;
+	list_remove(tmp);			/* remove frame from free_head */
+	list_append(tmp, &zone->busy_head);	/* append frame to busy_head */
+	zone->free_count--;
+	zone->busy_count++;
+	
+	v = zone->base + (frame - zone->frames) * FRAME_SIZE;
+	
+	if (flags & FRAME_KA)
+		v = PA2KA(v);
+	
+	spinlock_unlock(&zone->lock);
+	
+	spinlock_unlock(&zone_head_lock);
 	cpu_priority_restore(pri);
-
-	if (flags & FRAME_PANIC)
-		panic("unable to allocate frame\n");
-		
-	/* TODO: implement sleeping logic here */
-	panic("sleep not supported\n");
-	
-	goto loop;
-}
-
-/*
- * Free a frame.
+	
+	return v;
+}
+
+/** Free a frame.
+ *
+ * Find respective frame structrue for supplied addr.
+ * Decrement frame reference count.
+ * If it drops to zero, move the frame structure to free list.
+ *
+ * @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE.
  */
 void frame_free(__address addr)
 {
 	pri_t pri;
-	__u32 frame;
-
+	link_t *cur;
+	zone_t *z;
+	zone_t *zone = NULL;
+	frame_t *frame;
+	
+	ASSERT(addr % FRAME_SIZE == 0);
+	
 	pri = cpu_priority_high();
-	spinlock_lock(&framelock);
-	
-	frame = IS_KA(addr) ? KA2PA(addr) : addr;
-	frame /= FRAME_SIZE;
-	if (frame < frames) {
-		int m, n;
-	
-		m = frame / 8;
-		n = frame % 8;
-	
-		if (frame_bitmap[m] & (1<<n)) {
-			frame_bitmap[m] &= ~(1<<n);
-			frames_free++;
-		}
-		else panic("frame already free\n");
-	}
-	else panic("frame number too big\n");
-	
-	spinlock_unlock(&framelock);
+	spinlock_lock(&zone_head_lock);
+	
+	/*
+	 * First, find host frame zone for addr.
+	 */
+	for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
+		z = list_get_instance(cur, zone_t, link);
+		
+		spinlock_lock(&z->lock);
+		
+		if (IS_KA(addr))
+			addr = KA2PA(addr);
+		
+		/*
+		 * Check if addr belongs to z.
+		 */
+		if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) {
+			zone = z;
+			break;
+		}
+		spinlock_unlock(&z->lock);
+	}
+	
+	ASSERT(zone != NULL);
+	
+	frame = &zone->frames[(addr - zone->base)/FRAME_SIZE];
+	ASSERT(frame->refcount);
+
+	if (!--frame->refcount) {
+		list_remove(&frame->link);			/* remove frame from busy_head */
+		list_append(&frame->link, &zone->free_head);	/* append frame to free_head */
+		zone->free_count++;
+		zone->busy_count--;
+	}
+	
+	spinlock_unlock(&zone->lock);	
+	
+	spinlock_unlock(&zone_head_lock);
 	cpu_priority_restore(pri);
 }
 
-/*
- * Don't use this function for normal allocation. Use frame_alloc() instead.
- * Use this function to declare that some special frame is not free.
+/** Mark frame not free.
+ *
+ * Find respective frame structrue for supplied addr.
+ * Increment frame reference count and move the frame structure to busy list.
+ *
+ * @param addr Address of the frame to be marked. It must be a multiple of FRAME_SIZE.
  */
 void frame_not_free(__address addr)
 {
 	pri_t pri;
-	__u32 frame;
+	link_t *cur;
+	zone_t *z;
+	zone_t *zone = NULL;
+	frame_t *frame;
+	
+	ASSERT(addr % FRAME_SIZE == 0);
 	
 	pri = cpu_priority_high();
-	spinlock_lock(&framelock);
-	frame = IS_KA(addr) ? KA2PA(addr) : addr;
-	frame /= FRAME_SIZE;
-	if (frame < frames) {
-		int m, n;
-
-		m = frame / 8;
-		n = frame % 8;
-	
-		if ((frame_bitmap[m] & (1<<n)) == 0) {	
-			frame_bitmap[m] |= (1<<n);
-			frames_free--;	
-		}
-	}
-	spinlock_unlock(&framelock);
+	spinlock_lock(&zone_head_lock);
+	
+	/*
+	 * First, find host frame zone for addr.
+	 */
+	for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {
+		z = list_get_instance(cur, zone_t, link);
+		
+		spinlock_lock(&z->lock);
+		
+		if (IS_KA(addr))
+			addr = KA2PA(addr);
+		
+		/*
+		 * Check if addr belongs to z.
+		 */
+		if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) {
+			zone = z;
+			break;
+		}
+		spinlock_unlock(&z->lock);
+	}
+	
+	ASSERT(zone != NULL);
+	
+	frame = &zone->frames[(addr - zone->base)/FRAME_SIZE];
+
+	if (!frame->refcount) {
+		frame->refcount++;
+
+		list_remove(&frame->link);			/* remove frame from free_head */
+		list_append(&frame->link, &zone->busy_head);	/* append frame to busy_head */
+		zone->free_count--;
+		zone->busy_count++;
+	}
+	
+	spinlock_unlock(&zone->lock);	
+	
+	spinlock_unlock(&zone_head_lock);
 	cpu_priority_restore(pri);
 }
 
+/** Mark frame region not free.
+ *
+ * Mark frame region not free.
+ *
+ * @param start First address.
+ * @param stop Last address.
+ */
 void frame_region_not_free(__address start, __address stop)
 {
-	__address a;
-
-	start /= FRAME_SIZE;
-	stop /= FRAME_SIZE;
-	for (a = start; a <= stop; a++)
-		frame_not_free(a * FRAME_SIZE);
-}
+        __address a;
+
+        start /= FRAME_SIZE;
+        stop /= FRAME_SIZE;
+        for (a = start; a <= stop; a++)
+                frame_not_free(a * FRAME_SIZE);
+}
+
 
 /** Initialize zonekeeping
@@ -297,34 +362,3 @@
 	frame->refcount = 0;
 	link_initialize(&frame->link);
-	frame->zone = zone;
-}
-
-/** Get address of physical frame from its frame structure
- *
- * Get address of physical frame from its frame structure.
- *
- * @param frame Frame structure of the queried frame address.
- *
- * @return Address of frame associated with the argument.
- */
-__address frame_get_address(frame_t *frame)
-{
-	__address v;
-	zone_t *z;
-	pri_t pri;
-	
-	z = frame->zone;
-	
-	pri = cpu_priority_high();
-	spinlock_lock(&z->lock);
-
-	v = z->base + (frame - z->frames) * FRAME_SIZE;
-	
-	if (z->flags & FRAME_KA)
-		v = PA2KA(v);
-
-	spinlock_unlock(&z->lock);
-	cpu_priority_restore(pri);
-	
-	return v;
-}
+}
