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, int bCanAlloc);
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) + n_pages / 8);
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;
100 rd->Bitmap = (void*)&rd->PhysPages[ n_pages ];
102 for( int i = 0; i < n_pages; i ++ )
104 rd->PhysPages[i] = MM_AllocPhys();
105 if( !rd->PhysPages[i] ) {
111 return &rd->RootDir.Inode.Node;
114 void RAMDisk_Unmount(tVFS_Node *Node)
116 Log_Warning("RAMDisk", "TODO: Impliment unmounting");
119 // --- Directories ---
120 char *RAMDisk_ReadDir(tVFS_Node *Node, int Index)
122 tRAMDisk_Dir *dir = Node->ImplPtr;
123 for( tRAMDisk_DirEnt *d = dir->FirstEnt; d; d = d->Next )
126 return strdup(d->Name);
131 tVFS_Node *RAMDisk_FindDir(tVFS_Node *Node, const char *Name)
133 tRAMDisk_Dir *dir = Node->ImplPtr;
134 for( tRAMDisk_DirEnt *d = dir->FirstEnt; d; d = d->Next )
136 if( strcmp(d->Name, Name) == 0 )
137 return &d->Inode->Node;
143 int RAMDisk_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
145 tRAMDisk_Dir *dir = Node->ImplPtr;
146 if( RAMDisk_FindDir(Node, Name) != NULL )
149 tRAMDisk_DirEnt *de = malloc( sizeof(tRAMDisk_DirEnt) + strlen(Name) + 1 );
151 de->NameLen = strlen(Name);
152 strcpy(de->Name, Name);
154 if( Flags & VFS_FFLAG_DIRECTORY ) {
155 tRAMDisk_Dir *newdir = calloc(1, sizeof(tRAMDisk_Dir));
156 newdir->Inode.Node.Type = &gRAMDisk_DirNodeType;
157 de->Inode = &newdir->Inode;
160 tRAMDisk_File *newfile = calloc(1, sizeof(tRAMDisk_File));
161 newfile->Inode.Node.Type = &gRAMDisk_FileNodeType;
162 de->Inode = &newfile->Inode;
164 de->Inode->Disk = dir->Inode.Disk;
165 de->Inode->Node.Flags = Flags;
166 de->Inode->Node.ImplPtr = de->Inode;
168 RAMDisk_int_RefFile(de->Inode);
172 dir->LastEnt->Next = de;
180 int RAMDisk_Link(tVFS_Node *DirNode, const char *Name, tVFS_Node *FileNode)
182 tRAMDisk_Dir *dir = DirNode->ImplPtr;
185 for( dp = dir->FirstEnt; dp; dp = dp->Next )
187 if( strcmp(dp->Name, Name) == 0 )
191 dp = malloc( sizeof(tRAMDisk_DirEnt) + strlen(Name) + 1 );
193 dp->Inode = FileNode->ImplPtr;
194 RAMDisk_int_RefFile(dp->Inode);
195 strcpy(dp->Name, Name);
199 dir->LastEnt->Next = dp;
207 int RAMDisk_Unlink(tVFS_Node *Node, const char *Name)
209 tRAMDisk_Dir *dir = Node->ImplPtr;
210 tRAMDisk_DirEnt *dp, *p = NULL;
212 // TODO: Is locking needed?
214 for( dp = dir->FirstEnt; dp; p = dp, dp = dp->Next )
216 if( strcmp(dp->Name, Name) == 0 )
221 RAMDisk_int_DerefFile( dp->Inode );
224 dir->FirstEnt = dp->Next;
227 if( dir->LastEnt == dp )
235 size_t _DoIO(tRAMDisk_File *File, off_t Offset, size_t Size, void *Buffer, int bRead)
241 if( Offset >= File->Size ) return 0;
243 if( Offset + Size > File->Size ) Size = File->Size - Size;
245 if( Size == 0 ) return 0;
247 page = Offset / PAGE_SIZE;
251 page_virt = _GetPage(File, page++, !bRead);
252 if(!page_virt) return 0;
254 if( Offset + Size <= PAGE_SIZE )
257 memcpy(Buffer, page_virt + Offset, Size);
259 memcpy(page_virt + Offset, Buffer, Size);
264 memcpy(Buffer, page_virt + Offset, PAGE_SIZE - Offset);
266 memcpy(page_virt + Offset, Buffer, PAGE_SIZE - Offset);
267 Buffer += PAGE_SIZE - Offset;
268 rem -= PAGE_SIZE - Offset;
270 while( rem >= PAGE_SIZE )
272 _DropPage(page_virt);
273 page_virt = _GetPage(File, page++, !bRead);
274 if(!page_virt) return Size - rem;
277 memcpy(Buffer, page_virt, PAGE_SIZE);
279 memcpy(page_virt, Buffer, PAGE_SIZE);
287 page_virt = _GetPage(File, page, !bRead);
288 if(!page_virt) return Size - rem;
290 memcpy(Buffer, page_virt, rem);
292 memcpy(page_virt, Buffer, rem);
295 _DropPage(page_virt);
300 size_t RAMDisk_Read(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer)
302 tRAMDisk_File *file = Node->ImplPtr;
304 return _DoIO(file, Offset, Size, Buffer, 1);
307 size_t RAMDisk_Write(tVFS_Node *Node, off_t Offset, size_t Size, const void *Buffer)
309 tRAMDisk_File *file = Node->ImplPtr;
311 // TODO: Limit checks?
312 if( Offset == file->Size )
315 return _DoIO(file, Offset, Size, (void*)Buffer, 0);