2 * Acess2 Kernel - RAM Disk Support
3 * - By John Hodge (thePowersGang)
12 #define VERSION VER2(0,1)
14 #define MIN_RAMDISK_SIZE (1*1024*1024)
15 #define MAX_RAMDISK_SIZE (64*1024*1024)
18 int RAMDisk_Install(char **Arguments);
19 void RAMDisk_Cleanup(void);
20 // --- Mount/Unmount ---
21 tVFS_Node *RAMDisk_InitDevice(const char *Device, const char **Options);
22 void RAMDisk_Unmount(tVFS_Node *Node);
23 // --- Directories ---
24 char *RAMDisk_ReadDir(tVFS_Node *Node, int Index);
25 tVFS_Node *RAMDisk_FindDir(tVFS_Node *Node, const char *Name);
26 int RAMDisk_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
27 int RAMDisk_Link(tVFS_Node *DirNode, const char *Name, tVFS_Node *Node);
28 int RAMDisk_Unlink(tVFS_Node *Node, const char *Name);
30 size_t RAMDisk_Read(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer);
31 size_t RAMDisk_Write(tVFS_Node *Node, off_t Offset, size_t Size, const void *Buffer);
33 void RAMDisk_int_RefFile(tRAMDisk_Inode *Inode);
34 void RAMDisk_int_DerefFile(tRAMDisk_Inode *Inode);
35 void *_GetPage(tRAMDisk_File *File, int Page);
36 void _DropPage(void *Page);
39 MODULE_DEFINE(0, VERSION, FS_RAMDisk, RAMDisk_Install, RAMDisk_Cleanup, NULL);
40 tVFS_Driver gRAMDisk_Driver = {
42 .InitDevice = RAMDisk_InitDevice,
43 .Unmount = RAMDisk_Unmount
44 // TODO: GetNodeFromInode
46 tVFS_NodeType gRAMDisk_DirNodeType = {
47 .ReadDir = RAMDisk_ReadDir,
48 .FindDir = RAMDisk_FindDir,
49 .MkNod = RAMDisk_MkNod,
50 // .Link = RAMDisk_Link,
51 // .Unlink = RAMDisk_Unink
53 tVFS_NodeType gRAMDisk_FileNodeType = {
55 .Write = RAMDisk_Write
59 int RAMDisk_Install(char **Arguments)
61 VFS_AddDriver( &gRAMDisk_Driver );
65 void RAMDisk_Cleanup(void)
72 tVFS_Node *RAMDisk_InitDevice(const char *Device, const char **Options)
79 for( int i = 0; Options[i]; i ++ )
81 if( strcmp(Options[i], "megs") == '=' )
83 size = atoi(Options[i] + 5) * 1024 * 1024;
88 if( size > MAX_RAMDISK_SIZE || size < MIN_RAMDISK_SIZE )
91 int n_pages = size / PAGE_SIZE;
93 rd = calloc(1, sizeof(tRAMDisk) + n_pages * sizeof(tPAddr));
94 rd->MaxPages = n_pages;
95 rd->RootDir.Inode.Disk = rd;
96 rd->RootDir.Inode.Node.ImplPtr = &rd->RootDir;
97 rd->RootDir.Inode.Node.Flags = VFS_FFLAG_DIRECTORY;
98 rd->RootDir.Inode.Node.Size = -1;
99 rd->RootDir.Inode.Node.Type = &gRAMDisk_DirNodeType;
101 return &rd->RootDir.Inode.Node;
104 void RAMDisk_Unmount(tVFS_Node *Node)
106 Log_Warning("RAMDisk", "TODO: Impliment unmounting");
109 // --- Directories ---
110 char *RAMDisk_ReadDir(tVFS_Node *Node, int Index)
112 tRAMDisk_Dir *dir = Node->ImplPtr;
113 for( tRAMDisk_DirEnt *d = dir->FirstEnt; d; d = d->Next )
116 return strdup(d->Name);
121 tVFS_Node *RAMDisk_FindDir(tVFS_Node *Node, const char *Name)
123 tRAMDisk_Dir *dir = Node->ImplPtr;
124 for( tRAMDisk_DirEnt *d = dir->FirstEnt; d; d = d->Next )
126 if( strcmp(d->Name, Name) == 0 )
127 return &d->Inode->Node;
133 int RAMDisk_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
135 tRAMDisk_Dir *dir = Node->ImplPtr;
136 if( RAMDisk_FindDir(Node, Name) != NULL )
139 tRAMDisk_DirEnt *de = malloc( sizeof(tRAMDisk_DirEnt) + strlen(Name) + 1 );
141 de->NameLen = strlen(Name);
142 strcpy(de->Name, Name);
144 if( Flags & VFS_FFLAG_DIRECTORY ) {
145 tRAMDisk_Dir *newdir = calloc(1, sizeof(tRAMDisk_Dir));
146 newdir->Inode.Node.Type = &gRAMDisk_DirNodeType;
147 de->Inode = &newdir->Inode;
150 tRAMDisk_File *newfile = calloc(1, sizeof(tRAMDisk_File));
151 newfile->Inode.Node.Type = &gRAMDisk_FileNodeType;
152 de->Inode = &newfile->Inode;
154 de->Inode->Disk = dir->Inode.Disk;
155 de->Inode->Node.Flags = Flags;
156 de->Inode->Node.ImplPtr = de->Inode;
158 RAMDisk_int_RefFile(de->Inode);
162 dir->LastEnt->Next = de;
170 int RAMDisk_Link(tVFS_Node *DirNode, const char *Name, tVFS_Node *FileNode)
172 tRAMDisk_Dir *dir = DirNode->ImplPtr;
175 for( dp = dir->FirstEnt; dp; dp = dp->Next )
177 if( strcmp(dp->Name, Name) == 0 )
181 dp = malloc( sizeof(tRAMDisk_DirEnt) + strlen(Name) + 1 );
183 dp->Inode = FileNode->ImplPtr;
184 RAMDisk_int_RefFile(dp->Inode);
185 strcpy(dp->Name, Name);
189 dir->LastEnt->Next = dp;
197 int RAMDisk_Unlink(tVFS_Node *Node, const char *Name)
199 tRAMDisk_Dir *dir = Node->ImplPtr;
200 tRAMDisk_DirEnt *dp, *p = NULL;
202 // TODO: Is locking needed?
204 for( dp = dir->FirstEnt; dp; p = dp, dp = dp->Next )
206 if( strcmp(dp->Name, Name) == 0 )
211 RAMDisk_int_DerefFile( dp->Inode );
214 dir->FirstEnt = dp->Next;
217 if( dir->LastEnt == dp )
225 size_t RAMDisk_Read(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer)
227 tRAMDisk_File *file = Node->ImplPtr;
232 if( Offset >= file->Size )
235 if( Offset + Size > file->Size )
236 Size = file->Size - Size;
241 page_ofs = Offset / PAGE_SIZE;
245 page_virt = _GetPage(file, page_ofs++);
246 if( Offset + Size <= PAGE_SIZE ) {
247 memcpy(Buffer, page_virt + Offset, Size);
251 memcpy(Buffer, page_virt + Offset, PAGE_SIZE - Offset);
252 Buffer += PAGE_SIZE - Offset;
253 rem -= PAGE_SIZE - Offset;
255 while( rem >= PAGE_SIZE )
257 _DropPage(page_virt);
258 page_virt = _GetPage(file, page_ofs++);
259 memcpy(Buffer, page_virt, PAGE_SIZE);
266 page_virt = _GetPage(file, page_ofs);
267 memcpy(Buffer, page_virt, rem);
270 _DropPage(page_virt);
275 size_t RAMDisk_Write(tVFS_Node *Node, off_t Offset, size_t Size, const void *Buffer)