stdlibc: ~several fixes
[meinos.git] / kernel2 / memphys.c
blobcd951db4a97e7a0dc5fcd2d2d1d2e83ccd4ab0fa
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 (addr==NULL) return;
64 if (memphys_stackptr==memphys_stackend) {
65 // use pushed page as stackpage
66 if (paging_map(memphys_stackend,addr,0,1)<0) panic("Error while mapping stackpage: 0x%x",memphys_stackend);
67 memphys_stackend += PAGE_SIZE/sizeof(void*);
69 else {
70 // just push page on stack
71 *memphys_stackptr = addr;
72 memphys_stackptr++;
76 /**
77 * Pops an address from stack
78 * @return Address popped from stack
79 * @todo Check whether address is already used for DMA
81 void *memphys_pop() {
82 void *page = NULL;
83 if (memphys_stackptr>memphys_stackbase) {
84 if (memphys_stackptr-memphys_stackend>PAGE_SIZE) {
85 // free stackpage and return it
86 memphys_stackend -= PAGE_SIZE;
87 paging_unmap(memphys_stackend);
88 page = memphys_stackend;
90 else {
91 // just get page from stack
92 memphys_stackptr--;
93 page = *memphys_stackptr;
96 else panic("Ran out of memory\n");
97 return page;
101 * Returns the amount of remaining memory
102 * @return Amount of remaining memory in bytes
104 size_t memphys_memleft() {
105 return (((size_t)memphys_stackptr)-((size_t)memphys_stackbase))*PAGE_SIZE/4;
109 * Initializes DMA management
110 * @return Success?
112 int memphys_dma_init() {
113 memphys_dma_bitmap_size = MEMPHYS_DMALIMIT/(PAGE_SIZE*8);
114 memphys_dma_bitmap = malloc(memphys_dma_bitmap_size);
115 // memory until free memory (BDA, Kernel Code, Stack)
116 memset(memphys_dma_bitmap,0xFF,FREEPHYS_ADDRESS/(PAGE_SIZE*8));
117 // free pages
118 memset(((void*)memphys_dma_bitmap)+FREEPHYS_ADDRESS/(PAGE_SIZE*8),0,memphys_dma_bitmap_size-FREEPHYS_ADDRESS/(PAGE_SIZE*8));
119 return 0;
123 * Gets free DMA pages
124 * @param pages Amount of requested pages
125 * @return Address of first page
127 void *memphys_dma_alloc(size_t pages) {
128 size_t i;
129 size_t found = 0;
130 for (i=0;i<MEMPHYS_DMALIMIT/PAGE_SIZE;i++) {
131 if (!(memphys_dma_bitmap[i/(8*sizeof(int))]&(1<<(i%(8*sizeof(int)))))) found++;
132 else found = 0;
133 if (found==pages) {
134 size_t j;
135 for (j=i-(found-1);j<=i;j++) memphys_dma_bitmap[j/(8*sizeof(int))] |= 1<<(j%(8*sizeof(int)));
136 return (void*)((i-(found-1))*PAGE_SIZE);
139 return NULL;
143 * Frees a DMA page
144 * @param addr Address of DMA page
146 void memphys_dma_free(void *addr) {
147 size_t i = ((size_t)addr)/PAGE_SIZE;
148 memphys_dma_bitmap[i/(8*sizeof(int))] &= ~(1<<(i%(8*sizeof(int))));