f8422bbd7dfbafdbeb33b4691cbf628712d62839
[tpg/acess2.git] / Kernel / vfs / mmap.c
1 /*
2  * Acess2 VFS
3  * - Open, Close and ChDir
4  */
5 #define DEBUG   0
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
15 {
16         tVFS_MMapPageBlock      *Next;
17         Uint64  BaseOffset;     // Must be a multiple of MMAP_PAGES_PER_BLOCK*PAGE_SIZE
18         tPAddr  PhysAddrs[MMAP_PAGES_PER_BLOCK];
19 } tVFS_MMapPageBlock;
20
21 // === CODE ===
22 void *VFS_MMap(int *ErrNo, void *DestHint, size_t Length, int Protection, int Flags, int FD, Uint64 Offset)
23 {
24         tVFS_Handle     *h;
25         void    *mapping_dest;
26          int    npages, pagenum;
27         tVFS_MMapPageBlock      *pb, *prev;
28         
29         npages = ((Offset & (PAGE_SIZE-1)) + Length) / PAGE_SIZE;
30         pagenum = Offset / PAGE_SIZE;
31
32         mapping_dest = DestHint;        
33
34         // TODO: Locate space for the allocation
35         if( Flags & MAP_ANONYMOUS )
36         {
37                 MM_Allocate(mapping_dest);
38                 return mapping_dest;
39         }
40
41         h = VFS_GetHandle(FD);
42         if( !h || !h->Node )    return NULL;
43
44         // Search for existing mapping for each page
45         // - Sorted list of 16 page blocks
46         for(
47                 pb = h->Node->MMapInfo, prev = NULL;
48                 pb && pb->BaseOffset + MMAP_PAGES_PER_BLOCK < pagenum;
49                 prev = pb, pb = pb->Next
50                 );
51
52         if( !pb || pb->BaseOffset > pagenum )
53         {
54                 void    *old_pb = pb;
55                 // Allocate if needed
56                 pb = malloc( sizeof(tVFS_MMapPageBlock) );
57                 if(!pb) return NULL;
58                 pb->Next = old_pb;
59                 pb->BaseOffset = pagenum - pagenum % MMAP_PAGES_PER_BLOCK;
60                 memset(pb->PhysAddrs, 0, sizeof(pb->PhysAddrs));
61                 if(prev)
62                         prev->Next = pb;
63                 else
64                         h->Node->MMapInfo = pb;
65         }
66
67         while( npages -- )
68         {
69                 if( pb->PhysAddrs[pagenum - pb->BaseOffset] == 0 )
70                 {
71                         if( h->Node->MMap )
72                                 h->Node->MMap(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest);
73                         else
74                         {
75                                 // Allocate pages and read data
76                                 MM_Allocate(mapping_dest);
77                                 h->Node->Read(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest);
78                         }
79                         pb->PhysAddrs[pagenum -> pb->BaseOffset] = MM_GetPhysAddr( mapping_dest );
80                 }
81                 else
82                 {
83                         MM_Map( mapping_dest, pb->PhysAddrs[pagenum - pb->BaseOffset] );
84                 }
85                 pagenum ++;
86                 mapping_dest += PAGE_SIZE;
87                 
88                 // Roll on to next block if needed
89                 if(pagenum - pb->BaseOffset == MMAP_PAGES_PER_BLOCK)
90                 {
91                         if( pb->Next && pb->Next->BaseOffset == pagenum )
92                                 pb = pb->Next;
93                         else
94                         {
95                                 tVFS_MMapPageBlock      *oldpb = pb;
96                                 pb = malloc( sizeof(tVFS_MMapPageBlock) );
97                                 pb->Next = oldpb->Next;
98                                 pb->BaseOffset = pagenum;
99                                 memset(pb->PhysAddrs, 0, sizeof(pb->PhysAddrs));
100                                 oldpb->Next = pb;
101                         }
102                         pagenum = 0;
103                 }
104         }
105         
106         return NULL;
107 }
108
109 int VFS_MUnmap(int *ErrNo, void *Addr, size_t Length)
110 {
111         return 0;
112 }

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