summaryrefslogtreecommitdiff
path: root/src/kernel/mem.c
diff options
context:
space:
mode:
authorBenji Dial <Benji3.141@gmail.com>2020-08-11 11:33:21 -0400
committerBenji Dial <Benji3.141@gmail.com>2020-08-11 11:33:21 -0400
commit63167f223e1f54910f6b80e698390ee60aec79ee (patch)
tree41844f646bdcb5c9ba241bb5867c5e4f51737d52 /src/kernel/mem.c
parent77d7a284c02bc6b1b3a3a92ad5d957172cee9b81 (diff)
downloadportland-os-63167f223e1f54910f6b80e698390ee60aec79ee.tar.gz
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
Diffstat (limited to 'src/kernel/mem.c')
-rw-r--r--src/kernel/mem.c63
1 files changed, 63 insertions, 0 deletions
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 <stdint.h>
+#include <stdbool.h>
+#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