204 lines
5.3 KiB
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;
|
|
} |