Kernel - Bugfixing mmap and new binary loading
[tpg/acess2.git] / Kernel / vfs / mmap.c
1 /*
2  * Acess2 VFS
3  * - Open, Close and ChDir
4  */
5 #define DEBUG   1
6 #include <acess.h>
7 #include <vfs.h>
8 #include <vfs_ext.h>
9 #include <vfs_int.h>
10
11 #define MMAP_PAGES_PER_BLOCK    16
12
13 // === STRUCTURES ===
14 typedef struct sVFS_MMapPageBlock       tVFS_MMapPageBlock;
15 struct sVFS_MMapPageBlock
16 {
17         tVFS_MMapPageBlock      *Next;
18         Uint64  BaseOffset;     // Must be a multiple of MMAP_PAGES_PER_BLOCK*PAGE_SIZE
19         tPAddr  PhysAddrs[MMAP_PAGES_PER_BLOCK];
20 };
21
22 // === CODE ===
23 void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, Uint64 Offset)
24 {
25         tVFS_Handle     *h;
26         tVAddr  mapping_dest;
27          int    npages, pagenum;
28         tVFS_MMapPageBlock      *pb, *prev;
29
30         ENTER("pDestHint iLength xProtection xFlags xFD XOffset", DestHint, Length, Protection, Flags, FD, Offset);
31         
32         npages = ((Offset & (PAGE_SIZE-1)) + Length + (PAGE_SIZE - 1)) / PAGE_SIZE;
33         pagenum = Offset / PAGE_SIZE;
34
35         mapping_dest = (tVAddr)DestHint;        
36
37         // TODO: Locate space for the allocation
38
39         // Handle anonymous mappings
40         if( Flags & MMAP_MAP_ANONYMOUS )
41         {
42                 int i;
43                 for( i = 0; i < npages; i ++ ) {
44                         tPAddr rv = MM_Allocate(mapping_dest + i * PAGE_SIZE);
45                         if( !rv ) {
46                                 // TODO: Error
47                         }
48                 }
49                 LEAVE_RET('p', (void*)mapping_dest);
50         }
51
52         h = VFS_GetHandle(FD);
53         if( !h || !h->Node )    LEAVE_RET('n', NULL);
54
55         LOG("h = %p", h);
56
57         // Search for existing mapping for each page
58         // - Sorted list of 16 page blocks
59         for(
60                 pb = h->Node->MMapInfo, prev = NULL;
61                 pb && pb->BaseOffset + MMAP_PAGES_PER_BLOCK < pagenum;
62                 prev = pb, pb = pb->Next
63                 );
64
65         // - Allocate a block if needed
66         if( !pb || pb->BaseOffset > pagenum )
67         {
68                 void    *old_pb = pb;
69                 pb = malloc( sizeof(tVFS_MMapPageBlock) );
70                 if(!pb) LEAVE_RET('n', NULL);
71                 pb->Next = old_pb;
72                 pb->BaseOffset = pagenum - pagenum % MMAP_PAGES_PER_BLOCK;
73                 memset(pb->PhysAddrs, 0, sizeof(pb->PhysAddrs));
74                 if(prev)
75                         prev->Next = pb;
76                 else
77                         h->Node->MMapInfo = pb;
78         }
79
80         // - Map (and allocate) pages
81         while( npages -- )
82         {
83                 if( pb->PhysAddrs[pagenum - pb->BaseOffset] == 0 )
84                 {
85                         if( h->Node->MMap )
86                                 h->Node->MMap(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, (void*)mapping_dest);
87                         else
88                         {
89                                 // Allocate pages and read data
90                                 if( MM_Allocate(mapping_dest) == 0 ) {
91                                         // TODO: Unwrap
92                                         return NULL;
93                                 }
94                                 h->Node->Read(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, (void*)mapping_dest);
95                         }
96                         pb->PhysAddrs[pagenum - pb->BaseOffset] = MM_GetPhysAddr( mapping_dest );
97 //                      MM_SetPageInfo( pb->PhysAddrs[pagenum - pb->BaseOffset], h->Node, pagenum*PAGE_SIZE );
98                 }
99                 else
100                 {
101                         MM_Map( mapping_dest, pb->PhysAddrs[pagenum - pb->BaseOffset] );
102                 }
103                 pagenum ++;
104                 mapping_dest += PAGE_SIZE;
105                 
106                 // Roll on to next block if needed
107                 if(pagenum - pb->BaseOffset == MMAP_PAGES_PER_BLOCK)
108                 {
109                         if( pb->Next && pb->Next->BaseOffset == pagenum )
110                                 pb = pb->Next;
111                         else
112                         {
113                                 tVFS_MMapPageBlock      *oldpb = pb;
114                                 pb = malloc( sizeof(tVFS_MMapPageBlock) );
115                                 pb->Next = oldpb->Next;
116                                 pb->BaseOffset = pagenum;
117                                 memset(pb->PhysAddrs, 0, sizeof(pb->PhysAddrs));
118                                 oldpb->Next = pb;
119                         }
120                         pagenum = 0;
121                 }
122         }
123
124         LEAVE('n');     
125         return NULL;
126 }
127
128 int VFS_MUnmap(void *Addr, size_t Length)
129 {
130         return 0;
131 }

UCC git Repository :: git.ucc.asn.au