luxos/SysCore/memory/mmngr_ph.c

204 lines
5.3 KiB
C

/******************************************************
* Physical Memory Manager *
******************************************************/
#include <system.h>
#include <string.h>
#include "mmngr_ph.h"
#define PMMNGR_BLOCK_SIZE 4096 // block size (4k)
#define PMMNGR_BLOCK_ALIGN PMMNGR_BLOCK_SIZE // block alignment
struct memory_stack_entry{
word low;
byte high;
} __attribute__ ((__packed__));
typedef struct memory_stack_entry mstack;
static uint32_t _mmngr_memory_size=0; // size of physical memory
static uint32_t _mmngr_used_blocks=0; // number of blocks currently in use
static uint32_t _mmngr_max_blocks=0; // maximum number of available memory blocks
static uint32_t _mmngr_index = 0;
static mstack* _mmngr_memory_stack= 0; // memory stack
inline mstack mstack_pop ()
{
mstack temp;
temp.low = _mmngr_memory_stack[--_mmngr_index].low;
temp.high = _mmngr_memory_stack[_mmngr_index].high;
_mmngr_used_blocks++;
_mmngr_memory_stack[_mmngr_index].low = 0xFFFF;
_mmngr_memory_stack[_mmngr_index].high = 0xFF;
return temp;
}
inline void mstack_push (const mstack *block)
{
if (block->low == 0 && block-> high == 0) return;
_mmngr_memory_stack[_mmngr_index].low = block->low;
_mmngr_memory_stack[_mmngr_index].high = block->high;
_mmngr_index++;
_mmngr_used_blocks--;
}
inline byte mstack_test (const mstack *block)
{
uint32_t i;
for (i = 0; i < _mmngr_index; i++)
if (_mmngr_memory_stack[i].low == block->low && _mmngr_memory_stack[i].high == block->high) return 1;
return 0;
}
byte pmmngr_test_block (uint32_t block)
{
mstack temp;
temp.low = block & 0xFFFF;
temp.high = (block>>16) & 0xFF;
return mstack_test(&temp);
}
void pmmngr_free_block(void* address)
{
// Calculate block
mstack block;
uint32_t temp = (uint32_t)address / PMMNGR_BLOCK_SIZE;
block.low = temp & 0xFFFF;
block.high = (temp>>16) & 0xFF;
// Push it
mstack_push (&block);
}
void* pmmngr_alloc_block()
{
if (_mmngr_index == 0) return 0;// Out of memory
// pop a block
mstack block = mstack_pop();
// Calculate and return address;
void* address;
uint32_t temp = block.low | (block.high<<16);
address = (void *)(temp * PMMNGR_BLOCK_SIZE);
return address;
}
void pmmngr_init (size_t memSize, uint32_t stack) {
_mmngr_memory_size = memSize;
_mmngr_memory_stack = (mstack*) stack;
_mmngr_max_blocks = (_mmngr_memory_size*1024) / PMMNGR_BLOCK_SIZE;
_mmngr_used_blocks = _mmngr_max_blocks;
_mmngr_index = 0;
// By default, all of memory is in use
}
void pmmngr_init_region (physical_addr base, size_t size) {
mstack block;
unsigned int count = size / PMMNGR_BLOCK_SIZE;
unsigned int start = base / PMMNGR_BLOCK_SIZE;
for (; count!=0; count--) {
block.low = (start + count) & 0xFFFF;
block.high = ((start + count) << 16) & 0xFF;
mstack_push(&block);
}
}
void pmmngr_deinit_region (physical_addr base, size_t size) {
unsigned int start = base / PMMNGR_BLOCK_SIZE;
unsigned int count = size / PMMNGR_BLOCK_SIZE;
int temp;
unsigned int i;
unsigned int j;
// Find free blocks in the area and zero them
for (i = 0; i < _mmngr_index; i++) {
temp = (_mmngr_memory_stack[i].high << 16) | _mmngr_memory_stack[i].low;
if (temp >=start && temp < start+count)
{ _mmngr_memory_stack[i].high = 0;
_mmngr_memory_stack[i].low = 0;
}
}
// Eliminate zero blocks
for (i = 0; i<_mmngr_index; i++)
if (_mmngr_memory_stack[i].high == 0 && _mmngr_memory_stack[i].low == 0)
{
// Find next non-zero
for (j = i; _mmngr_memory_stack[j].high == 0 && _mmngr_memory_stack[j].low == 0; j++)
if (j == _mmngr_index-1) {
j = 0; break; }
if (j == 0) {
_mmngr_index = i;
break;
}
_mmngr_memory_stack[i].high = _mmngr_memory_stack[j].high;
_mmngr_memory_stack[i].low = _mmngr_memory_stack[j].low;
_mmngr_memory_stack[j].high = 0;
_mmngr_memory_stack[j].low = 0;
}
}
size_t pmmngr_get_memory_size () {
return _mmngr_memory_size;
}
uint32_t pmmngr_get_block_count () {
return _mmngr_max_blocks;
}
uint32_t pmmngr_get_use_block_count () {
return _mmngr_used_blocks;
}
uint32_t pmmngr_get_free_block_count () {
return _mmngr_index;
}
uint32_t pmmngr_get_block_size () {
return PMMNGR_BLOCK_SIZE;
}
void pmmngr_paging_enable (byte b) {
uint32_t temp;
temp = read_cr0();
// Enable
if (b) temp |= 0x80000000;
else temp &= ~0x80000000;
write_cr0(temp);
}
byte pmmngr_is_paging () {
uint32_t temp = read_cr0();
return ((temp&0x80000000)>0);
}
mstack* pmmngr_get_stack_addr()
{
return _mmngr_memory_stack;
}