Main Page | Directories | File List | Globals

bin_alloc.c

Go to the documentation of this file.
00001 /*
00002  * kernel_super/memory/bin_alloc.c
00003  *
00004  * Copyright (c) 2003-2004 Lukasz Dembinski <dembol@nasa.com.pl>
00005  * All Rights Reserved
00006  * 
00007  * Date:        2004/01
00008  * Author:      Lukasz Dembinski
00009  * Info:        bin_alloc.c core file
00010  * Contact:     mailto: <dembol@nasa.com.pl>
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 
Dokumentacje wygenerowano programem Doxygen 1.4.2 dla projektu Agnix