From: John Hodge Date: Sun, 17 Jul 2011 15:23:35 +0000 (+0800) Subject: Kernel - Adding support for MMap (untested) X-Git-Tag: rel0.10~39 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=8b7dec58d79aad0ba8467a15c353eade8ad5592b;p=tpg%2Facess2.git Kernel - Adding support for MMap (untested) --- diff --git a/Kernel/include/vfs.h b/Kernel/include/vfs.h index 248a1ac9..73161a1c 100644 --- a/Kernel/include/vfs.h +++ b/Kernel/include/vfs.h @@ -155,6 +155,7 @@ typedef struct sVFS_Node /** * \name VFS_Select() fields + * \note Used by the VFS internals, drivers should use VFS_Mark* * \{ */ int DataAvaliable; @@ -166,6 +167,15 @@ typedef struct sVFS_Node /** * \} */ + + /** + * \name VFS_MMap() fields + * \{ + */ + void *MMapInfo; + /** + * \} + */ /** * \name Common Functions diff --git a/Kernel/include/vfs_int.h b/Kernel/include/vfs_int.h index d4a533da..0d6b3b5d 100644 --- a/Kernel/include/vfs_int.h +++ b/Kernel/include/vfs_int.h @@ -35,6 +35,11 @@ typedef struct sVFS_Proc { tVFS_Handle Handles[]; } tVFS_Proc; +typedef struct sVFS_MMapPage { + Uint64 FileOffset; + tPAddr PAddr; +} tVFS_MMapPage; + // === GLOBALS === extern tVFS_Mount *gVFS_Mounts; diff --git a/Kernel/vfs/mmap.c b/Kernel/vfs/mmap.c new file mode 100644 index 00000000..f8422bbd --- /dev/null +++ b/Kernel/vfs/mmap.c @@ -0,0 +1,112 @@ +/* + * Acess2 VFS + * - Open, Close and ChDir + */ +#define DEBUG 0 +#include +#include +#include +#include + +#define MMAP_PAGES_PER_BLOCK 16 + +// === STRUCTURES === +typedef struct sVFS_MMapPageBlock +{ + tVFS_MMapPageBlock *Next; + Uint64 BaseOffset; // Must be a multiple of MMAP_PAGES_PER_BLOCK*PAGE_SIZE + tPAddr PhysAddrs[MMAP_PAGES_PER_BLOCK]; +} tVFS_MMapPageBlock; + +// === CODE === +void *VFS_MMap(int *ErrNo, void *DestHint, size_t Length, int Protection, int Flags, int FD, Uint64 Offset) +{ + tVFS_Handle *h; + void *mapping_dest; + int npages, pagenum; + tVFS_MMapPageBlock *pb, *prev; + + npages = ((Offset & (PAGE_SIZE-1)) + Length) / PAGE_SIZE; + pagenum = Offset / PAGE_SIZE; + + mapping_dest = DestHint; + + // TODO: Locate space for the allocation + if( Flags & MAP_ANONYMOUS ) + { + MM_Allocate(mapping_dest); + return mapping_dest; + } + + h = VFS_GetHandle(FD); + if( !h || !h->Node ) return NULL; + + // Search for existing mapping for each page + // - Sorted list of 16 page blocks + for( + pb = h->Node->MMapInfo, prev = NULL; + pb && pb->BaseOffset + MMAP_PAGES_PER_BLOCK < pagenum; + prev = pb, pb = pb->Next + ); + + if( !pb || pb->BaseOffset > pagenum ) + { + void *old_pb = pb; + // Allocate if needed + pb = malloc( sizeof(tVFS_MMapPageBlock) ); + if(!pb) return NULL; + pb->Next = old_pb; + pb->BaseOffset = pagenum - pagenum % MMAP_PAGES_PER_BLOCK; + memset(pb->PhysAddrs, 0, sizeof(pb->PhysAddrs)); + if(prev) + prev->Next = pb; + else + h->Node->MMapInfo = pb; + } + + while( npages -- ) + { + if( pb->PhysAddrs[pagenum - pb->BaseOffset] == 0 ) + { + if( h->Node->MMap ) + h->Node->MMap(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest); + else + { + // Allocate pages and read data + MM_Allocate(mapping_dest); + h->Node->Read(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest); + } + pb->PhysAddrs[pagenum -> pb->BaseOffset] = MM_GetPhysAddr( mapping_dest ); + } + else + { + MM_Map( mapping_dest, pb->PhysAddrs[pagenum - pb->BaseOffset] ); + } + pagenum ++; + mapping_dest += PAGE_SIZE; + + // Roll on to next block if needed + if(pagenum - pb->BaseOffset == MMAP_PAGES_PER_BLOCK) + { + if( pb->Next && pb->Next->BaseOffset == pagenum ) + pb = pb->Next; + else + { + tVFS_MMapPageBlock *oldpb = pb; + pb = malloc( sizeof(tVFS_MMapPageBlock) ); + pb->Next = oldpb->Next; + pb->BaseOffset = pagenum; + memset(pb->PhysAddrs, 0, sizeof(pb->PhysAddrs)); + oldpb->Next = pb; + } + pagenum = 0; + } + } + + return NULL; +} + +int VFS_MUnmap(int *ErrNo, void *Addr, size_t Length) +{ + return 0; +}