Minor fixes
[meinos.git] / kernel2 / memphys.c
blob8b513605b5011c97ae01657a5155d81fd2d1df0b
1 /*
2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
20 #include <memmap.h>
21 #include <memphys.h>
22 #include <multiboot.h>
23 #include <paging.h>
24 #include <limits.h>
25 #include <debug.h>
26 #include <string.h>
27 #include <memkernel.h>
28 #include <kprint.h>
30 /**
31 * Initializes physical memory management
32 * @return -1=Success; 0=Failure
34 int memphys_init() {
35 memphys_memory = (multiboot_get_memlower()+multiboot_get_memlower());
37 memphys_stackbase = (void*)STACKDATA_ADDRESS;
38 memphys_stackend = memphys_stackbase;
39 memphys_stackptr = memphys_stackbase;
41 // push free memory on stack
42 size_t i = 0;
43 void *addr;
44 size_t size;
45 multiboot_mmap_type_t type;
46 while (multiboot_get_mmap(i++,&addr,&size,&type)==0) {
47 if (type==MULTIBOOT_FREE) {
48 size_t j;
49 for (j=0;j<size/PAGE_SIZE;j++) {
50 if (addr+j*PAGE_SIZE>=(void*)FREEPHYS_ADDRESS) memphys_push(addr+j*PAGE_SIZE);
55 return 0;
58 /**
59 * Pushs an address on stack
60 * @param addr Address to push on stack
62 void memphys_push(void *addr) {
63 if (memphys_stackptr==memphys_stackend) {
64 // use pushed page as stackpage
65 if (paging_map(memphys_stackend,addr,0,1)<0) panic("Error while mapping stackpage: 0x%x",memphys_stackend);
66 memphys_stackend += PAGE_SIZE/sizeof(void*);
68 else {
69 // just push page on stack
70 *memphys_stackptr = addr;
71 memphys_stackptr++;
75 /**
76 * Pops an address from stack
77 * @return Address popped from stack
78 * @todo Check whether address is already used for DMA
80 void *memphys_pop() {
81 void *page = NULL;
82 if (memphys_stackptr>memphys_stackbase) {
83 if (memphys_stackptr-memphys_stackend>PAGE_SIZE) {
84 // free stackpage and return it
85 memphys_stackend -= PAGE_SIZE;
86 paging_unmap(memphys_stackend);
87 page = memphys_stackend;
89 else {
90 // just get page from stack
91 memphys_stackptr--;
92 page = *memphys_stackptr;
95 else panic("Ran out of memory\n");
96 return page;
99 /**
100 * Returns the amount of remaining memory
101 * @return Amount of remaining memory in bytes
103 size_t memphys_memleft() {
104 return (((size_t)memphys_stackptr)-((size_t)memphys_stackbase))*PAGE_SIZE/4;
108 * Initializes DMA management
109 * @return Success?
111 int memphys_dma_init() {
112 memphys_dma_bitmap_size = MEMPHYS_DMALIMIT/(PAGE_SIZE*8);
113 memphys_dma_bitmap = malloc(memphys_dma_bitmap_size);
114 // memory until free memory (BDA, Kernel Code, Stack)
115 memset(memphys_dma_bitmap,0xFF,FREEPHYS_ADDRESS/(PAGE_SIZE*8));
116 // free pages
117 memset(((void*)memphys_dma_bitmap)+FREEPHYS_ADDRESS/(PAGE_SIZE*8),0,memphys_dma_bitmap_size-FREEPHYS_ADDRESS/(PAGE_SIZE*8));
118 return 0;
122 * Gets free DMA pages
123 * @param pages Amount of requested pages
124 * @return Address of first page
126 void *memphys_dma_alloc(size_t pages) {
127 size_t i;
128 size_t found = 0;
129 for (i=0;i<MEMPHYS_DMALIMIT/PAGE_SIZE;i++) {
130 if (!(memphys_dma_bitmap[i/(8*sizeof(int))]&(1<<(i%(8*sizeof(int)))))) found++;
131 else found = 0;
132 if (found==pages) {
133 size_t j;
134 for (j=i-(found-1);j<=i;j++) memphys_dma_bitmap[j/(8*sizeof(int))] |= 1<<(j%(8*sizeof(int)));
135 return (void*)((i-(found-1))*PAGE_SIZE);
138 return NULL;
142 * Frees a DMA page
143 * @param addr Address of DMA page
145 void memphys_dma_free(void *addr) {
146 size_t i = ((size_t)addr)/PAGE_SIZE;
147 memphys_dma_bitmap[i/(8*sizeof(int))] &= ~(1<<(i%(8*sizeof(int))));