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

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