00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <agnix/agnix.h>
00015 #include <agnix/adi/adi.h>
00016 #include <asm/bitops.h>
00017 #include <asm/memory.h>
00018 #include <asm/paging.h>
00019
00020 #include <agnix/memory.h>
00021 #include <agnix/bugs.h>
00022 #include <agnix/console.h>
00023
00024 #define MOD_NAME "MEM: "
00025 #define NO_PAGE 0
00026
00027 struct bin_allocator_s bin_alloc;
00028 extern struct allocator_s main_alloc;
00029
00030 extern void (*put_free_pages_fn)(u32 addr, u8 order);
00031 extern u32 (*get_free_pages_fn)(u8 order);
00032
00033 extern char _text;
00034 extern char _end;
00035
00036 void bin_reserve_pages(struct bin_allocator_s *allocator, u32 start_page, u32 size)
00037 {
00038 u32 idx_start = start_page;
00039 u32 idx_end = idx_start + size;
00040 u32 i;
00041
00042 if (idx_end >= main_alloc.mem_size_pages)
00043 return;
00044
00045 for (i = idx_start; i < idx_end; i++) {
00046 set_bit((int)i, (void *)allocator->mem_table);
00047 }
00048 }
00049
00050 void bin_free_pages(struct bin_allocator_s *allocator, u32 start_page, u32 size)
00051 {
00052 u32 idx_start = start_page - main_alloc.mem_start;
00053 u32 idx_end = idx_start + size;
00054 u32 i;
00055
00056 for (i = idx_start; i < idx_end; i++) {
00057 clear_bit((int)i, (void *)allocator->mem_table);
00058 }
00059 }
00060
00061 u32 _bin_get_free_pages(struct bin_allocator_s *allocator, u32 size)
00062 {
00063 u32 i = 0;
00064 u32 j = 0;
00065
00066 for (i = 0; i < main_alloc.mem_size_pages; i++) {
00067 if (test_bit((int)i, (void *)allocator->mem_table))
00068 continue;
00069
00070 for (j = 0; j < size; j++) {
00071 if (test_bit((int)(i + j), (void *)allocator->mem_table))
00072 goto bad_area;
00073 }
00074
00075 return (main_alloc.mem_start + i);
00076
00077 bad_area:
00078 i += j;
00079 }
00080
00081 return NO_PAGE;
00082 }
00083
00084 void bin_put_free_pages(u32 addr, u32 pages)
00085 {
00086 bin_free_pages(&bin_alloc, (addr - PAGE_OFFSET) >> PAGE_SHIFT, pages);
00087 }
00088
00089 void bin_put_free_pages_order(u32 addr, u8 order)
00090 {
00091 return bin_put_free_pages(addr, (u32)(1 << order));
00092 }
00093
00094 u32 bin_get_free_pages(u32 pages)
00095 {
00096 u32 page;
00097
00098 page = _bin_get_free_pages(&bin_alloc, pages);
00099
00100 if (page != NO_PAGE)
00101 bin_reserve_pages(&bin_alloc, page, pages);
00102 else
00103 return NO_PAGE;
00104
00105 return ((page << PAGE_SHIFT) + PAGE_OFFSET);
00106 }
00107
00108 u32 bin_get_free_pages_order(u8 order)
00109 {
00110 return bin_get_free_pages((u32)(1 << order));
00111 }
00112
00113 int bin_put_all_free_pages(void)
00114 {
00115 int i;
00116 int free_count = 0;
00117
00118 for (i = DMA_START_PAGES; i < DMA_MAX_PAGES; i++)
00119 put_free_dma_pages(phys_to_virt((u32)(i << PAGE_SHIFT)), 0);
00120
00121 for (i = DMA_MAX_PAGES; i < main_alloc.mem_size_pages; i++) {
00122 if (test_bit((int)i, (void *)(bin_alloc.mem_table)))
00123 continue;
00124
00125 put_free_pages(phys_to_virt((u32)(i << PAGE_SHIFT)), 0);
00126 free_count++;
00127 }
00128
00129 printk(MOD_NAME "there are %d free pages (%dKB)\n", free_count, free_count << 2);
00130 printk(MOD_NAME "mem_size=%d pages, mem_table=%d pages, dma_area=%d\n", main_alloc.mem_size_pages, main_alloc.mem_table_size_pages, DMA_MAX_PAGES - DMA_START_PAGES);
00131
00132 return free_count;
00133 }
00134
00135 void bin_alloc_fn_init(void)
00136 {
00137 get_free_pages_fn = bin_get_free_pages_order;
00138 put_free_pages_fn = bin_put_free_pages_order;
00139 }
00140
00141 void bin_reserve_system_pages(void)
00142 {
00143 bin_reserve_pages(&bin_alloc, 0, 2);
00144 bin_reserve_pages(&bin_alloc, DMA_START_PAGES, DMA_MAX_PAGES);
00145
00146 bin_reserve_pages(&bin_alloc, virt_to_page((u32)&_text), ((u32)&_end - (u32)&_text) >> PAGE_SHIFT);
00147
00148 bin_reserve_pages(&bin_alloc, virt_to_phys((u32)(bin_alloc.mem_table)) >> PAGE_SHIFT,
00149 main_alloc.mem_table_size_pages);
00150 }
00151
00152 void __init bin_alloc_init(u32 *mem_table, u32 mem_start, u32 mem_end)
00153 {
00154 memset(&bin_alloc, 0, sizeof(bin_alloc));
00155
00156 bin_alloc.mem_table = mem_table;
00157 main_alloc.mem_start = mem_start;
00158 main_alloc.mem_end = mem_end;
00159 main_alloc.mem_size = mem_end - mem_start;
00160 main_alloc.mem_size_pages = main_alloc.mem_size >> 2;
00161 main_alloc.mem_table_size_pages = (((main_alloc.mem_size_pages + ((1 << 3) - 1)) >> 3) + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
00162
00163 memset((void *)mem_table, 0xFF, main_alloc.mem_table_size_pages << PAGE_SHIFT);
00164
00165 bin_alloc_fn_init();
00166 }
00167