started memory allocator, allocated final stack, added move_init_stack
[lugburz] / src / amiga / mem.c
1 #include <stdio.h>
2 #include "serial.h"
3 #include "mem.h"
4 #include "amigalib.h"
5 #include "debug.h"
6
7 #define MAGIC   0xa55a
8 #define STACK_SIZE      4096
9
10 enum {
11         MEM_FAST,
12         MEM_SLOW,
13         MEM_CHIP,
14         MEM_USED        = 0x8000
15 };
16
17 struct memrange {
18         uint16_t magic;
19         uint16_t attr;
20         uint32_t size;
21         struct memrange *next;
22         unsigned char start[];
23 };
24
25 #define NUM_POOLS       3
26 static struct memrange *pool[NUM_POOLS];
27 static uint32_t stack_base, stack_top;
28
29 extern int _mem_start;
30
31 void move_init_stack(uint32_t newtop);  /* in startup.s */
32
33 int init_mem(void)
34 {
35         int i;
36         struct memrange *mr;
37         struct alib_memnode *mem;
38         uint32_t mem_start = (uint32_t)&_mem_start;
39
40         printf("mem_start: %lu\n", mem_start);
41
42         printf("Memory ranges:\n");
43         mem = execbase->memlist.head;
44         while(mem->n_next) {
45                 unsigned long start, end, size;
46                 char *stype;
47                 int type;
48
49                 /* assume we're dealing with at least 64k blocks */
50                 start = (unsigned long)mem->start & 0xff0000;
51                 end = ((unsigned long)mem->end + 0xffff) & 0xff0000;
52                 size = end - start;
53
54                 if(mem->attrib & ALIB_MEMF_CHIP) {
55                         stype = "chip";
56                         type = MEM_CHIP;
57                 } else if(mem->attrib & ALIB_MEMF_FAST) {
58                         if(start >= 0xc00000 && end <= 0xd80000) {
59                                 stype = "slow";
60                                 type = MEM_SLOW;
61                         } else {
62                                 stype = "fast";
63                                 type = MEM_FAST;
64                         }
65                 } else {
66                         printf("ignoring memory range %06lx - %06lx of unknown type: %u\n",
67                                         start, end, mem->attrib);
68                         mem = mem->n_next;
69                         continue;
70                 }
71
72                 printf(" %06lx - %06lx: %s (%ldk)\n", start, end, stype, size >> 10);
73                 mem = mem->n_next;
74
75                 if(mem_start >= start && mem_start < end) {
76                         size -= mem_start - start;
77                         start = mem_start;
78                 }
79
80                 mr = (struct memrange*)start;
81                 mr->magic = MAGIC;
82                 mr->attr = type;
83                 mr->size = size - sizeof *mr;
84                 mr->next = pool[type];
85                 pool[type] = mr;
86         }
87
88         /* allocate stack space at the top of a memory range, order of preference:
89          * fast, slow, chip
90          */
91         for(i=0; i<NUM_POOLS; i++) {
92                 mr = pool[i];
93                 if(mr && mr->size >= STACK_SIZE) {
94                         stack_top = (uint32_t)mr->start + mr->size;
95                         stack_base = stack_top - STACK_SIZE;
96                         mr->size -= STACK_SIZE;
97                         break;
98                 }
99         }
100
101         if(!stack_base) {
102                 panic("Failed to allocate stack, no suitable memory ranges found!\n");
103         }
104
105         printf("Allocated %dk stack space: %06lx - %06lx\n", STACK_SIZE >> 10, stack_base, stack_top);
106         move_init_stack(stack_top);
107
108         return 0;
109 }