From 63167f223e1f54910f6b80e698390ee60aec79ee Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Tue, 11 Aug 2020 11:33:21 -0400 Subject: lots of progress currently, BAR fields of IDE drives are all returning zero, and the ATA read function isn't working. i'm not sure why. i'm going to work on VESA next, and come back to the IDE driver later --- src/kernel/mem.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/kernel/mem.c (limited to 'src/kernel/mem.c') diff --git a/src/kernel/mem.c b/src/kernel/mem.c new file mode 100644 index 0000000..2e8173d --- /dev/null +++ b/src/kernel/mem.c @@ -0,0 +1,63 @@ +#include +#include +#include "panic.h" + +#define DYNAMIC_START (0x10000000) +#define DYNAMIC_END (DYNAMIC_START + 65536 * 4096) +#define PAGE_TO_ADDR(n) ((void *)(DYNAMIC_START | ((n) << 12))) +#define ADDR_TO_PAGE(n) (((uint32_t)(n) & ~DYNAMIC_START) >> 12) + +#define MMAP_START (0x00010000) +#define PAGE_USED(n) ((*(uint8_t *)(MMAP_START + (n >> 3)) >> (n & 7)) & 1) +#define CLEAR_PAGE(n) *(uint8_t *)(MMAP_START + (n >> 3)) &= ~(1 << (n & 7)) +#define SET_PAGE(n) *(uint8_t *)(MMAP_START + (n >> 3)) |= 1 << (n & 7) + +extern const void kernel_bss_end; + +uint16_t pages_left; + +void init_mmap() { + volatile uint8_t *end_ptr = (uint8_t *)(DYNAMIC_END - 1); + uint8_t end_val = *end_ptr; + *end_ptr = (uint8_t)~end_val; + if (*end_ptr != (uint8_t)~end_val) + panic("Not enough memory. Must have at least 512MiB."); + + for (uint32_t *m = (uint32_t *)MMAP_START; m < (uint32_t *)(MMAP_START + (65536 / 8)); ++m) + *m = 0; + + uint16_t kernel_bss_pages = (((uint32_t)&kernel_bss_end - DYNAMIC_START - 1) >> 12) + 1; + for (uint16_t i = 0; i < kernel_bss_pages; ++i) + SET_PAGE(i); + + pages_left = 65536 - kernel_bss_pages; +} + +//very inneficient algorithm, just returns first hole big enough. +//a smarter algorithm might pick the smallest one available, +//and go by bytes (or dwords) instead of bits where possible. +void *allocate_pages(uint16_t n) { + uint16_t run = 0; + + for (uint32_t page = 0; page < 65536; ++page) { + if (PAGE_USED(page)) + run = 0; + else if (++run == n) { + uint16_t start = page - run + 1; + for (uint32_t i = start; i <= page; ++i) + SET_PAGE(i); + pages_left -= n; + return PAGE_TO_ADDR(start); + } + } + + return 0; +} + +//in the future, change this to go by bytes or dwords instead of bits. +void free_pages(void *ptr, uint16_t n) { + uint16_t page = ADDR_TO_PAGE(ptr); + for (uint32_t i = page; i < page + n; ++i) + CLEAR_PAGE(i); + pages_left += n; +} \ No newline at end of file -- cgit v1.2.3