From 2479df06d56b576e1e221ebff5a53384ce8bb971 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 21 May 2012 23:19:05 +0800 Subject: [PATCH] Modules/RAMDisk - Non-linking RAMDisk driver --- .../Modules/Filesystems/RAMDisk/Makefile | 9 + .../Modules/Filesystems/RAMDisk/ramdisk.c | 280 ++++++++++++++++++ .../Modules/Filesystems/RAMDisk/ramdisk.h | 63 ++++ 3 files changed, 352 insertions(+) create mode 100644 KernelLand/Modules/Filesystems/RAMDisk/Makefile create mode 100644 KernelLand/Modules/Filesystems/RAMDisk/ramdisk.c create mode 100644 KernelLand/Modules/Filesystems/RAMDisk/ramdisk.h diff --git a/KernelLand/Modules/Filesystems/RAMDisk/Makefile b/KernelLand/Modules/Filesystems/RAMDisk/Makefile new file mode 100644 index 00000000..b1f39800 --- /dev/null +++ b/KernelLand/Modules/Filesystems/RAMDisk/Makefile @@ -0,0 +1,9 @@ +# +# RAMDisk Makfile +# + +OBJ = ramdisk.o +NAME = RAMDisk + +-include ../Makefile.tpl + diff --git a/KernelLand/Modules/Filesystems/RAMDisk/ramdisk.c b/KernelLand/Modules/Filesystems/RAMDisk/ramdisk.c new file mode 100644 index 00000000..9b6d2c02 --- /dev/null +++ b/KernelLand/Modules/Filesystems/RAMDisk/ramdisk.c @@ -0,0 +1,280 @@ +/* + * Acess2 Kernel - RAM Disk Support + * - By John Hodge (thePowersGang) + * + * ramdisk.c + * - Core File + */ +#define DEBUG 0 +#include +#include +#include "ramdisk.h" +#define VERSION VER2(0,1) + +#define MIN_RAMDISK_SIZE (1*1024*1024) +#define MAX_RAMDISK_SIZE (64*1024*1024) + +// === PROTOTYPES === + int RAMDisk_Install(char **Arguments); +void RAMDisk_Cleanup(void); +// --- Mount/Unmount --- +tVFS_Node *RAMDisk_InitDevice(const char *Device, const char **Options); +void RAMDisk_Unmount(tVFS_Node *Node); +// --- Directories --- +char *RAMDisk_ReadDir(tVFS_Node *Node, int Index); +tVFS_Node *RAMDisk_FindDir(tVFS_Node *Node, const char *Name); + int RAMDisk_MkNod(tVFS_Node *Node, const char *Name, Uint Flags); + int RAMDisk_Link(tVFS_Node *DirNode, const char *Name, tVFS_Node *Node); + int RAMDisk_Unlink(tVFS_Node *Node, const char *Name); +// --- Files --- +size_t RAMDisk_Read(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer); +size_t RAMDisk_Write(tVFS_Node *Node, off_t Offset, size_t Size, const void *Buffer); +// --- Internals -- +void RAMDisk_int_RefFile(tRAMDisk_Inode *Inode); +void RAMDisk_int_DerefFile(tRAMDisk_Inode *Inode); +void *_GetPage(tRAMDisk_File *File, int Page); +void _DropPage(void *Page); + +// === GLOBALS === +MODULE_DEFINE(0, VERSION, FS_RAMDisk, RAMDisk_Install, RAMDisk_Cleanup, NULL); +tVFS_Driver gRAMDisk_Driver = { + .Name = "RAMDisk", + .InitDevice = RAMDisk_InitDevice, + .Unmount = RAMDisk_Unmount + // TODO: GetNodeFromInode + }; +tVFS_NodeType gRAMDisk_DirNodeType = { + .ReadDir = RAMDisk_ReadDir, + .FindDir = RAMDisk_FindDir, + .MkNod = RAMDisk_MkNod, +// .Link = RAMDisk_Link, +// .Unlink = RAMDisk_Unink + }; +tVFS_NodeType gRAMDisk_FileNodeType = { + .Read = RAMDisk_Read, + .Write = RAMDisk_Write + }; + +// === CODE === +int RAMDisk_Install(char **Arguments) +{ + VFS_AddDriver( &gRAMDisk_Driver ); + return 0; +} + +void RAMDisk_Cleanup(void) +{ + +} + + +// --- Mount/Unmount +tVFS_Node *RAMDisk_InitDevice(const char *Device, const char **Options) +{ + size_t size = 0; + tRAMDisk *rd; + + if( Options ) + { + for( int i = 0; Options[i]; i ++ ) + { + if( strcmp(Options[i], "megs") == '=' ) + { + size = atoi(Options[i] + 5) * 1024 * 1024; + } + } + } + + if( size > MAX_RAMDISK_SIZE || size < MIN_RAMDISK_SIZE ) + return NULL; + + int n_pages = size / PAGE_SIZE; + + rd = calloc(1, sizeof(tRAMDisk) + n_pages * sizeof(tPAddr)); + rd->MaxPages = n_pages; + rd->RootDir.Inode.Disk = rd; + rd->RootDir.Inode.Node.ImplPtr = &rd->RootDir; + rd->RootDir.Inode.Node.Flags = VFS_FFLAG_DIRECTORY; + rd->RootDir.Inode.Node.Size = -1; + rd->RootDir.Inode.Node.Type = &gRAMDisk_DirNodeType; + + return &rd->RootDir.Inode.Node; +} + +void RAMDisk_Unmount(tVFS_Node *Node) +{ + Log_Warning("RAMDisk", "TODO: Impliment unmounting"); +} + +// --- Directories --- +char *RAMDisk_ReadDir(tVFS_Node *Node, int Index) +{ + tRAMDisk_Dir *dir = Node->ImplPtr; + for( tRAMDisk_DirEnt *d = dir->FirstEnt; d; d = d->Next ) + { + if( Index -- == 0 ) + return strdup(d->Name); + } + return NULL; +} + +tVFS_Node *RAMDisk_FindDir(tVFS_Node *Node, const char *Name) +{ + tRAMDisk_Dir *dir = Node->ImplPtr; + for( tRAMDisk_DirEnt *d = dir->FirstEnt; d; d = d->Next ) + { + if( strcmp(d->Name, Name) == 0 ) + return &d->Inode->Node; + } + + return NULL; +} + +int RAMDisk_MkNod(tVFS_Node *Node, const char *Name, Uint Flags) +{ + tRAMDisk_Dir *dir = Node->ImplPtr; + if( RAMDisk_FindDir(Node, Name) != NULL ) + return -1; + + tRAMDisk_DirEnt *de = malloc( sizeof(tRAMDisk_DirEnt) + strlen(Name) + 1 ); + de->Next = NULL; + de->NameLen = strlen(Name); + strcpy(de->Name, Name); + + if( Flags & VFS_FFLAG_DIRECTORY ) { + tRAMDisk_Dir *newdir = calloc(1, sizeof(tRAMDisk_Dir)); + newdir->Inode.Node.Type = &gRAMDisk_DirNodeType; + de->Inode = &newdir->Inode; + } + else { + tRAMDisk_File *newfile = calloc(1, sizeof(tRAMDisk_File)); + newfile->Inode.Node.Type = &gRAMDisk_FileNodeType; + de->Inode = &newfile->Inode; + } + de->Inode->Disk = dir->Inode.Disk; + de->Inode->Node.Flags = Flags; + de->Inode->Node.ImplPtr = de->Inode; + + RAMDisk_int_RefFile(de->Inode); + + // TODO: Lock? + if(dir->FirstEnt) + dir->LastEnt->Next = de; + else + dir->FirstEnt = de; + dir->LastEnt = de; + + return 0; +} + +int RAMDisk_Link(tVFS_Node *DirNode, const char *Name, tVFS_Node *FileNode) +{ + tRAMDisk_Dir *dir = DirNode->ImplPtr; + tRAMDisk_DirEnt *dp; + + for( dp = dir->FirstEnt; dp; dp = dp->Next ) + { + if( strcmp(dp->Name, Name) == 0 ) + return -1; + } + + dp = malloc( sizeof(tRAMDisk_DirEnt) + strlen(Name) + 1 ); + dp->Next = NULL; + dp->Inode = FileNode->ImplPtr; + RAMDisk_int_RefFile(dp->Inode); + strcpy(dp->Name, Name); + + // TODO: Lock? + if(dir->FirstEnt) + dir->LastEnt->Next = dp; + else + dir->FirstEnt = dp; + dir->LastEnt = dp; + + return 0; +} + +int RAMDisk_Unlink(tVFS_Node *Node, const char *Name) +{ + tRAMDisk_Dir *dir = Node->ImplPtr; + tRAMDisk_DirEnt *dp, *p = NULL; + + // TODO: Is locking needed? + + for( dp = dir->FirstEnt; dp; p = dp, dp = dp->Next ) + { + if( strcmp(dp->Name, Name) == 0 ) + break ; + } + if( !dp ) return -1; + + RAMDisk_int_DerefFile( dp->Inode ); + + if( !p ) + dir->FirstEnt = dp->Next; + else + p->Next = dp->Next; + if( dir->LastEnt == dp ) + dir->LastEnt = p; + free(dp); + + return 0; +} + +// --- Files --- +size_t RAMDisk_Read(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer) +{ + tRAMDisk_File *file = Node->ImplPtr; + int page_ofs; + char *page_virt; + size_t rem; + + if( Offset >= file->Size ) + return 0; + + if( Offset + Size > file->Size ) + Size = file->Size - Size; + + if( Size == 0 ) + return 0; + + page_ofs = Offset / PAGE_SIZE; + Offset %= PAGE_SIZE; + rem = Size; + + page_virt = _GetPage(file, page_ofs++); + if( Offset + Size <= PAGE_SIZE ) { + memcpy(Buffer, page_virt + Offset, Size); + return Size; + } + + memcpy(Buffer, page_virt + Offset, PAGE_SIZE - Offset); + Buffer += PAGE_SIZE - Offset; + rem -= PAGE_SIZE - Offset; + + while( rem >= PAGE_SIZE ) + { + _DropPage(page_virt); + page_virt = _GetPage(file, page_ofs++); + memcpy(Buffer, page_virt, PAGE_SIZE); + Buffer += PAGE_SIZE; + rem -= PAGE_SIZE; + } + + if( rem > 0 ) + { + page_virt = _GetPage(file, page_ofs); + memcpy(Buffer, page_virt, rem); + } + + _DropPage(page_virt); + + return Size; +} + +size_t RAMDisk_Write(tVFS_Node *Node, off_t Offset, size_t Size, const void *Buffer) +{ + return 0; +} + + diff --git a/KernelLand/Modules/Filesystems/RAMDisk/ramdisk.h b/KernelLand/Modules/Filesystems/RAMDisk/ramdisk.h new file mode 100644 index 00000000..46925093 --- /dev/null +++ b/KernelLand/Modules/Filesystems/RAMDisk/ramdisk.h @@ -0,0 +1,63 @@ +/* + * Acess2 Kernel - RAM Disk Support + * - By John Hodge (thePowersGang) + * + * ramdisk.h + * - Core header + */ +#ifndef _RAMDISK_H_ +#define _RAMDISK_H_ + +#include + +typedef struct sRAMDisk_Inode tRAMDisk_Inode; +typedef struct sRAMDisk_File tRAMDisk_File; +typedef struct sRAMDisk_DirEnt tRAMDisk_DirEnt; +typedef struct sRAMDisk_Dir tRAMDisk_Dir; +typedef struct sRAMDisk tRAMDisk; + +struct sRAMDisk_Inode +{ + tRAMDisk *Disk; + tVFS_Node Node; + int Type; // 0: Normal, 1: Dir, 2: Symlink + int nLink; +}; + +struct sRAMDisk_File +{ + tRAMDisk_Inode Inode; + size_t Size; + int nAllocPageSlots; + Uint32 PagesDirect[12]; + Uint32 Indirect1Page; // PAGE_SIZE/sizeof(Uint32) = 1024 on x86 + Uint32 Indirect2Page; // ~1 Million on x86 +}; + +struct sRAMDisk_DirEnt +{ + tRAMDisk_DirEnt *Next; + tRAMDisk_Inode *Inode; + Uint8 NameLen; + char Name[]; +}; + +struct sRAMDisk_Dir +{ + tRAMDisk_Inode Inode; + + tRAMDisk_DirEnt *FirstEnt; + tRAMDisk_DirEnt *LastEnt; +}; + +struct sRAMDisk +{ + tRAMDisk_Dir RootDir; + + int MaxPages; + int nUsedPages; + tPAddr PhysPages[]; +}; + +#endif + -- 2.20.1