Code cleanup.
[v86d.git] / v86_mem.c
blob725a4124eb89ca1c030c0cfac6e9d048481e771b
1 #include <fcntl.h>
2 #include <string.h>
3 #include <sys/mman.h>
4 #include "v86.h"
6 #define REAL_MEM_BLOCKS 0x100
8 u8 *real_mem = NULL;
10 struct mem_block {
11 unsigned int size : 20;
12 unsigned int free : 1;
15 static struct {
16 int ready;
17 int count;
18 struct mem_block blocks[REAL_MEM_BLOCKS];
19 } mem_info = { 0 };
21 static int read_file(char *name, void *p, size_t n)
23 int fd;
25 fd = open(name, O_RDONLY);
27 if (fd == -1) {
28 perror("open");
29 return 0;
32 if (read(fd, p, n) != n) {
33 perror("read");
34 close(fd);
35 return 0;
38 close(fd);
40 return 1;
43 static int map_file(void *start, size_t length, int prot, int flags, char *name, long offset)
45 void *m;
46 int fd;
48 fd = open(name, (flags & MAP_SHARED) ? O_RDWR : O_RDONLY);
50 if (fd == -1) {
51 perror("open");
52 return 0;
55 m = mmap(start, length, prot, flags, fd, offset);
57 if (m == (void *)-1) {
58 perror("mmap");
59 close(fd);
60 return 0;
63 close(fd);
64 return 1;
67 static int real_mem_init(void)
69 if (mem_info.ready)
70 return 0;
72 if (!map_file((void *)REAL_MEM_BASE, REAL_MEM_SIZE,
73 PROT_READ | PROT_WRITE | PROT_EXEC,
74 MAP_FIXED | MAP_PRIVATE, "/dev/zero", 0))
75 return 0;
77 real_mem = (u8*)0;
79 mem_info.ready = 1;
80 mem_info.count = 1;
81 mem_info.blocks[0].size = REAL_MEM_SIZE;
82 mem_info.blocks[0].free = 1;
84 return 0;
87 static void real_mem_deinit(void)
89 if (mem_info.ready) {
90 munmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE);
91 mem_info.ready = 0;
95 static void insert_block(int i)
97 memmove(mem_info.blocks + i + 1, mem_info.blocks + i,
98 (mem_info.count - i) * sizeof(struct mem_block));
99 mem_info.count++;
102 static void delete_block(int i)
104 mem_info.count--;
105 memmove(mem_info.blocks + i, mem_info.blocks + i + 1,
106 (mem_info.count - i) * sizeof(struct mem_block));
109 void *v86_mem_alloc(int size)
111 int i;
112 char *r = (char *)REAL_MEM_BASE;
114 if (!mem_info.ready)
115 return NULL;
117 if (mem_info.count == REAL_MEM_BLOCKS)
118 return NULL;
120 size = (size + 15) & ~15;
122 for (i = 0; i < mem_info.count; i++) {
123 if (mem_info.blocks[i].free && size < mem_info.blocks[i].size) {
124 insert_block(i);
126 mem_info.blocks[i].size = size;
127 mem_info.blocks[i].free = 0;
128 mem_info.blocks[i + 1].size -= size;
130 return (void *)r;
133 r += mem_info.blocks[i].size;
136 return NULL;
139 void v86_mem_free(void *m)
141 int i;
142 char *r = (char *)REAL_MEM_BASE;
144 if (!mem_info.ready)
145 return;
147 i = 0;
148 while (m != (void *)r) {
149 r += mem_info.blocks[i].size;
150 i++;
151 if (i == mem_info.count)
152 return;
155 mem_info.blocks[i].free = 1;
157 if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free) {
158 mem_info.blocks[i].size += mem_info.blocks[i + 1].size;
159 delete_block(i + 1);
162 if (i - 1 >= 0 && mem_info.blocks[i - 1].free) {
163 mem_info.blocks[i - 1].size += mem_info.blocks[i].size;
164 delete_block(i);
168 static inline void set_bit(unsigned int bit, void *array)
170 unsigned char *a = array;
171 a[bit / 8] |= (1 << (bit % 8));
174 inline u16 get_int_seg(int i)
176 return *(u16 *)(i * 4 + 2);
179 inline u16 get_int_off(int i)
181 return *(u16 *)(i * 4);
184 int v86_mem_init(void)
186 void *m;
187 int fd_mem;
189 if (real_mem_init())
190 return 1;
192 if (!map_file((void *)IVTBDA_BASE, IVTBDA_SIZE,
193 PROT_READ | PROT_WRITE | PROT_EXEC,
194 MAP_FIXED | MAP_PRIVATE, "/dev/zero", 0))
196 real_mem_deinit();
197 return 1;
200 if (!read_file("/dev/mem", (void *)IVTBDA_BASE, IVTBDA_SIZE)) {
201 munmap((void *)IVTBDA_BASE, IVTBDA_SIZE);
202 real_mem_deinit();
203 return 1;
206 if (!map_file((void *)0xa0000, 0x100000 - 0xa0000,
207 PROT_READ | PROT_WRITE,
208 MAP_FIXED | MAP_SHARED, "/dev/mem", 0xa0000))
210 munmap((void *)IVTBDA_BASE, IVTBDA_SIZE);
211 real_mem_deinit();
212 return 1;
215 return 0;
218 void v86_mem_cleanup(void)
220 munmap((void *)IVTBDA_BASE, IVTBDA_SIZE);
221 munmap((void *)0xa0000, 0x100000 - 0xa0000);
223 real_mem_deinit();