#include "clib.h"
#include "phmem.h"
#define MEMORY 32768
/*
* qui c'e` il gestore delle pagine di memoria.
* ad ogni pagina e` associato un contatore che indica da quanti task
* e` utilizzata. quando il contatore e` 0 la pagina e` libera.
* la massima quantita` di memoria e` determinata dalla costante
* MAX_PAGES. nota che indica il numero massimo di pagine allocabili
* a partire da FIRST_PAGE, che e` la prima pagina utilizzabile, mentre
* LAST_PAGE e` l'ultima pagina utilizzabile.
*
* esempio di come viene caricato il tutto :
*
*
*
* ____________ indirizzo limite per l'heap, massimo IBMH + #MEMORY
* | HEAP |
* | |
* |________|__ Indirizzo Base della Memoria Heap (IBMH)
* | kernel |
* |________|___ indirizzo base del kernel
*
* ..... ______________ eventuali programmi che usano memoria > 1Mb,
* | ????? | come ad esempio smartdrv
* |___________ 110000h
* | HMA |
* |________|__ 100000h
* | |
* |bios/video/UMB
* |________|__ 0A0000h
* | dos |
* |________|__ 000000h
*
*
*
* NOTA: la prima pagina di memoria non puo` avere indirizzo < di 110000h
*
* NOTA: queste funzioni non devono essere interrotte dallo scheduler
*
*
* LREV 23/sept/97
*/
#define MAX_PAGES (MEMORY/4)
#define LAST_PAGE last_page
#define FIRST_PAGE first_page
#define MEM_START (FIRST_PAGE * 4096)
// array, tiene taccia delle pagine libere/occupate
// allineato a cache-line
static s8 mem_pages[MAX_PAGES];// _align(32);
// numero di pagine UTILIZZABILI (che e` sempre <= MAX_PAGES)
static int num_pages;
// PRIMA pagina utilizzabile
static int last_page;
// indirizzo ULTIMA pagina UTILIZZABILE
static int first_page;
phaddr_t alloc_free_pages(int num)
{
int count = num, i;
for (i = 0; i < num_pages; i++) {
if (mem_pages[i] == 0) { // se e` una pagina libera
if (--count == 0) {
int j;
for (j = 0; j < num; j++) {
mem_pages[i-j] = 1; // marca come usate
}
i = (i - num + 1) * 4096+MEM_START;
ASSERT((i shr 12) >= FIRST_PAGE);
ASSERT((i shr 12) <= LAST_PAGE);
return (phaddr_t)i;
}
} else count = num;
}
WARNING("return NULL");
return 0;
}
phaddr_t alloc_free_page(void)
{
int i;
for (i = 0; i < num_pages; i++)
if (mem_pages[i] == 0) {
mem_pages[i] = 1;
i = i*4096+MEM_START;
return (phaddr_t)i;
}
WARNING("return NULL");
return 0;
}
phaddr_t alloc_pages_at(phaddr_t base, int num)
{
int page = (u32)base >> 12, i;
for (i = 0; i < num; i++, page++) {
if (page >= FIRST_PAGE && page <= LAST_PAGE) {
mem_pages[page - FIRST_PAGE]++;
ASSERT(mem_pages[page - FIRST_PAGE] > 0);
} else {
WARNING("return NULL");
return 0;
}
}
return base;
}
int free_pages(phaddr_t a, int num)
{
int page = (u32)a >> 12, i;
for (i = 0; i < num; i++, page++) {
if ((page >= FIRST_PAGE) && (page <= LAST_PAGE)) {
if (mem_pages[page - FIRST_PAGE] > 0)
mem_pages[page - FIRST_PAGE]--;
return 0;
} else {
WARNING("EFAUL in page %xh", page);
return EFAULT;
}
}
return 0; /* se num == 0 */
}
int free_page(phaddr_t a)
{
int page = (u32)a >> 12;
if (page >= FIRST_PAGE && page <= LAST_PAGE) {
if (mem_pages[page - FIRST_PAGE] > 0)
--(mem_pages[page - FIRST_PAGE]);
return 0;
}
WARNING("EFAUL in page %xh", page);
return EFAULT;
}
int ph_memory_setup(phaddr_t heap_base, int npages)
{
FIRST_PAGE = (u32)(heap_base + 0xFFF) >> 12; // arrotonda per eccesso
num_pages = npages;
if (num_pages > MAX_PAGES) num_pages = MAX_PAGES;
LAST_PAGE = (FIRST_PAGE + num_pages) - 1;
ASSERT(FIRST_PAGE >= 272);
DEBUG_VERBOSE("first page %xh ", FIRST_PAGE);
DEBUG_VERBOSE("last page %xh ", LAST_PAGE);
DEBUG_VERBOSE("num_pages %xh\n", num_pages);
return num_pages;
}
int get_free_pages(void)
{
int f = 0, i;
for (i = 0; i < num_pages; i++)
if (mem_pages[i] == 0) f++;
return f;
}
int get_total_pages(void)
{
return num_pages;
}
phaddr_t get_fault_address(void)
{
return (phaddr_t)(LAST_PAGE shl 12) + 4096;
}