1 /*
2 * Open Hack'Ware BIOS memory management.
3 *
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License V2
8 * as published by the Free Software Foundation
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include <stdlib.h>
21 #include "bios.h"
22
23 #if 0
24 static uint8_t *page_bitmap;
25 static uint32_t memory_size;
26
27 static void mark_page_in_use (uint32_t page_nb)
28 {
29 uint32_t offset, bit;
30
31 offset = page_nb >> 3;
32 bit = page_nb & 7;
33 page_bitmap[offset] |= 1 << bit;
34 }
35
36 static void mark_page_free (uint32_t page_nb)
37 {
38 uint32_t offset, bit;
39
40 offset = page_nb >> 3;
41 bit = page_nb & 7;
42 page_bitmap[offset] &= ~(1 << bit);
43 }
44
45 static int is_page_in_use (uint32_t page_nb)
46 {
47 uint32_t offset, bit;
48
49 offset = page_nb >> 3;
50 bit = page_nb & 7;
51
52 return (page_bitmap[offset] & (~(1 << bit))) != 0;
53 }
54
55 void mm_init (uint32_t memsize)
56 {
57 uint32_t page_start, page_ram_start, page, ram_start;
58 uint32_t nb_pages, bitmap_size;
59
60 /* Init bitmap */
61 ram_start = (uint32_t)(&_ram_start);
62 ram_start = (ram_start + (1 << 12) - 1) & ~((1 << 12) - 1);
63 page_bitmap = (void *)ram_start;
64 nb_pages = (memsize + (1 << 12) - 1) >> 12;
65 bitmap_size = (nb_pages + 7) >> 3;
66 /* First mark all pages as free */
67 memset(page_bitmap, 0, bitmap_size);
68 /* Mark all pages used by the BIOS as used (code + data + bitmap) */
69 page_start = (uint32_t)(0x05800000) >> 12; /* TO FIX */
70 ram_start += bitmap_size;
71 ram_start = (ram_start + (1 << 12) - 1) & ~((1 << 12) - 1);
72 page_ram_start = ram_start >> 12;
73 for (page = page_start; page < page_ram_start; page++)
74 mark_page_in_use(page);
75 memory_size = memsize;
76 }
77
78 void *page_get (int nb_pages)
79 {
80 uint32_t page_start, page_end, page;
81 int nb;
82
83 page_start = (uint32_t)(0x05800000) >> 12; /* TO FIX */
84 page_end = memory_size >> 12;
85 for (page = page_start; page < page_end; ) {
86 /* Skip all full "blocs" */
87 for (; page < page_end; page += 8) {
88 if (page_bitmap[page >> 3] != 0xFF)
89 break;
90 }
91 for (nb = 0; page < page_end; page++) {
92 if (!is_page_in_use(page)) {
93 nb++;
94 if (nb == nb_pages) {
95 /* Found ! */
96 for (; nb >= 0; nb--, page--)
97 mark_page_in_use(page);
98
99 return (void *)(page << 12);
100 }
101 }
102 }
103 }
104
105 return NULL;
106 }
107
108 void page_put (void *addr, int nb_pages)
109 {
110 uint32_t page_start, page_end, page;
111
112 page_start = (uint32_t)addr >> 12;
113 page_end = page_start + nb_pages;
114 for (page = page_start; page < page_end; page++) {
115 if (!is_page_in_use(page))
116 printf("ERROR: page %u has already been freed !\n", page);
117 mark_page_free(page);
118 }
119 }
120 #else
121 static uint8_t *page_alloc;
122
mm_init(unused uint32_t memsize)123 void mm_init (unused uint32_t memsize)
124 {
125 uint32_t ram_start;
126 ram_start = (uint32_t)(&_ram_start);
127 ram_start = (ram_start + (1 << 12) - 1) & ~((1 << 12) - 1);
128 page_alloc = (void *)ram_start;
129 }
130
page_get(unused int nb_pages)131 void *page_get (unused int nb_pages)
132 {
133 void *ret;
134
135 ret = page_alloc;
136 page_alloc += nb_pages << 12;
137 memset(ret, 0, nb_pages << 12);
138
139 return ret;
140 }
141
page_put(unused void * addr,unused int nb_pages)142 void page_put (unused void *addr, unused int nb_pages)
143 {
144 }
145 #endif
146