122 lines
2.9 KiB
C
122 lines
2.9 KiB
C
// mm.c
|
|
// Author: Josh Holtrop
|
|
// Created: 09/01/03
|
|
// Modified: 12/28/03
|
|
|
|
//The total amount of physical memory available (bytes, 1 bit per page)
|
|
#define BITMAP_SIZE 0x20000
|
|
dword mm_totalmem = 0;
|
|
dword mm_megabytes;
|
|
byte page_bitmap[BITMAP_SIZE]; //used to store a bit for each page that is used, 0 if available
|
|
//0x20000*(8 bits/byte)=0x100000 pages in 4gb total
|
|
|
|
//This function initializes the memory manager's linked list, filling it with the
|
|
// memory areas returned by bios interrupt 0x8E20
|
|
void mm_init()
|
|
{
|
|
dword memmap_entries = *(dword *)BOOT_MEMMAP_ENTRIES;
|
|
memmap_entry *maps = (memmap_entry *) BOOT_FIRST_MEMMAP;
|
|
dword a;
|
|
for (a = 0; a < BITMAP_SIZE; a++)
|
|
{
|
|
page_bitmap[a] = 0xFF; //all pages used
|
|
}
|
|
for (a = 0; a < memmap_entries; a++)
|
|
{
|
|
if (maps[a].attributes == 1) // (1) mem free to OS
|
|
{
|
|
mm_totalmem += maps[a].limit.lowdword;
|
|
if ((maps[a].base.lowdword + maps[a].limit.lowdword) >= (FREERAM_START+4096)) //goes past where we start freeram
|
|
{
|
|
if (maps[a].base.lowdword < FREERAM_START)
|
|
{
|
|
mm_pfreen(FREERAM_START, (maps[a].limit.lowdword - (FREERAM_START - maps[a].base.lowdword)) >> 12);
|
|
}
|
|
else
|
|
{
|
|
mm_pfreen(maps[a].base.lowdword, maps[a].limit.lowdword >> 12); //set the appropriate bits as "free" in the page bitmap
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (mm_totalmem % 0x100000)
|
|
mm_megabytes = (mm_totalmem >> 20) + 1;
|
|
else
|
|
mm_megabytes = mm_totalmem >> 20;
|
|
}
|
|
|
|
|
|
// This function frees a certain number of pages starting at the address
|
|
// specified in base for a length of pages pages
|
|
void mm_pfreen(dword base, dword pages)
|
|
{
|
|
dword a;
|
|
dword max = base + (pages << 12);
|
|
for (a = base; a < max; a += 4096)
|
|
{
|
|
mm_pfree(a);
|
|
}
|
|
}
|
|
|
|
|
|
// This function frees a single page
|
|
void mm_pfree(dword base)
|
|
{
|
|
// dword pageNumber = base >> 12; // >>12 == /4096
|
|
dword byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8
|
|
dword bitNumber = (base >> 12) % 8; //pageNumber % 8;
|
|
page_bitmap[byteNumber] = page_bitmap[byteNumber] & ((0x01 << bitNumber) ^ 0xFF);
|
|
}
|
|
|
|
|
|
// This function allocates a single page, returning its physical address
|
|
void *mm_palloc()
|
|
{
|
|
dword bite;
|
|
for (bite = 0; bite < BITMAP_SIZE; bite++)
|
|
{
|
|
if (page_bitmap[bite] != 0xFF) //there is an available page within this 8-page region
|
|
{
|
|
int bit;
|
|
for (bit = 0; bit < 8; bit++)
|
|
{
|
|
if (!(page_bitmap[bite] & (1 << bit))) //this bite/bit combination is available
|
|
{
|
|
page_bitmap[bite] = page_bitmap[bite] | (1 << bit); //set page as used
|
|
return (void *)((bite << 15) | (bit << 12));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0; //no free page
|
|
}
|
|
|
|
|
|
// This function reports the number of bytes of free physical memory
|
|
dword mm_freemem()
|
|
{
|
|
dword a;
|
|
dword pages = 0;
|
|
for (a = 0; a < BITMAP_SIZE; a++)
|
|
{
|
|
int bit;
|
|
for (bit = 0; bit < 8; bit++)
|
|
{
|
|
if (!(page_bitmap[a] & (1 << bit)))
|
|
pages++;
|
|
}
|
|
}
|
|
return pages << 12;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|