Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openhackware / src / mm.c
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
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
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
142 void page_put (unused void *addr, unused int nb_pages)
143 {
144 }
145 #endif