Modules/RAMDisk - Non-linking RAMDisk driver
[tpg/acess2.git] / KernelLand / Modules / Filesystems / RAMDisk / ramdisk.c
1 /*
2  * Acess2 Kernel - RAM Disk Support
3  * - By John Hodge (thePowersGang)
4  *
5  * ramdisk.c
6  * - Core File
7  */
8 #define DEBUG   0
9 #include <acess.h>
10 #include <modules.h>
11 #include "ramdisk.h"
12 #define VERSION VER2(0,1)
13
14 #define MIN_RAMDISK_SIZE        (1*1024*1024)
15 #define MAX_RAMDISK_SIZE        (64*1024*1024)
16
17 // === PROTOTYPES ===
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);
29 // --- Files ---
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);
32 // --- Internals --
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);
37
38 // === GLOBALS ===
39 MODULE_DEFINE(0, VERSION, FS_RAMDisk, RAMDisk_Install, RAMDisk_Cleanup, NULL);
40 tVFS_Driver     gRAMDisk_Driver = {
41         .Name = "RAMDisk",
42         .InitDevice = RAMDisk_InitDevice,
43         .Unmount = RAMDisk_Unmount
44         // TODO: GetNodeFromInode
45         };
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
52         };
53 tVFS_NodeType   gRAMDisk_FileNodeType = {
54         .Read  = RAMDisk_Read,
55         .Write = RAMDisk_Write
56         };
57
58 // === CODE ===
59 int RAMDisk_Install(char **Arguments)
60 {
61         VFS_AddDriver( &gRAMDisk_Driver );
62         return 0;
63 }
64
65 void RAMDisk_Cleanup(void)
66 {
67         
68 }
69
70
71 // --- Mount/Unmount
72 tVFS_Node *RAMDisk_InitDevice(const char *Device, const char **Options)
73 {
74         size_t  size = 0;
75         tRAMDisk        *rd;
76
77         if( Options ) 
78         {
79                 for( int i = 0; Options[i]; i ++ )
80                 {
81                         if( strcmp(Options[i], "megs") == '=' )
82                         {
83                                 size = atoi(Options[i] + 5) * 1024 * 1024;
84                         }
85                 }
86         }
87
88         if( size > MAX_RAMDISK_SIZE || size < MIN_RAMDISK_SIZE )
89                 return NULL;
90
91          int    n_pages = size / PAGE_SIZE;
92         
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;
100
101         return &rd->RootDir.Inode.Node;
102 }
103
104 void RAMDisk_Unmount(tVFS_Node *Node)
105 {
106         Log_Warning("RAMDisk", "TODO: Impliment unmounting");
107 }
108
109 // --- Directories ---
110 char *RAMDisk_ReadDir(tVFS_Node *Node, int Index)
111 {
112         tRAMDisk_Dir    *dir = Node->ImplPtr;
113         for( tRAMDisk_DirEnt *d = dir->FirstEnt; d; d = d->Next )
114         {
115                 if( Index -- == 0 )
116                         return strdup(d->Name);
117         }
118         return NULL;
119 }
120
121 tVFS_Node *RAMDisk_FindDir(tVFS_Node *Node, const char *Name)
122 {
123         tRAMDisk_Dir    *dir = Node->ImplPtr;
124         for( tRAMDisk_DirEnt *d = dir->FirstEnt; d; d = d->Next )
125         {
126                 if( strcmp(d->Name, Name) == 0 )
127                         return &d->Inode->Node;
128         }
129         
130         return NULL;
131 }
132
133 int RAMDisk_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
134 {
135         tRAMDisk_Dir    *dir = Node->ImplPtr;
136         if( RAMDisk_FindDir(Node, Name) != NULL )
137                 return -1;
138         
139         tRAMDisk_DirEnt *de = malloc( sizeof(tRAMDisk_DirEnt) + strlen(Name) + 1 );
140         de->Next = NULL;
141         de->NameLen = strlen(Name);
142         strcpy(de->Name, Name);
143
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;
148         }
149         else {
150                 tRAMDisk_File   *newfile = calloc(1, sizeof(tRAMDisk_File));
151                 newfile->Inode.Node.Type = &gRAMDisk_FileNodeType;
152                 de->Inode = &newfile->Inode;
153         }
154         de->Inode->Disk = dir->Inode.Disk;
155         de->Inode->Node.Flags = Flags;
156         de->Inode->Node.ImplPtr = de->Inode;
157
158         RAMDisk_int_RefFile(de->Inode);
159
160         // TODO: Lock?
161         if(dir->FirstEnt)
162                 dir->LastEnt->Next = de;
163         else
164                 dir->FirstEnt = de;
165         dir->LastEnt = de;
166
167         return 0;
168 }
169
170 int RAMDisk_Link(tVFS_Node *DirNode, const char *Name, tVFS_Node *FileNode)
171 {
172         tRAMDisk_Dir    *dir = DirNode->ImplPtr;
173         tRAMDisk_DirEnt *dp;
174
175         for( dp = dir->FirstEnt; dp; dp = dp->Next )
176         {
177                 if( strcmp(dp->Name, Name) == 0 )
178                         return -1;
179         }
180         
181         dp = malloc( sizeof(tRAMDisk_DirEnt) + strlen(Name) + 1 );
182         dp->Next = NULL;
183         dp->Inode = FileNode->ImplPtr;
184         RAMDisk_int_RefFile(dp->Inode);
185         strcpy(dp->Name, Name);
186
187         // TODO: Lock?  
188         if(dir->FirstEnt)
189                 dir->LastEnt->Next = dp;
190         else
191                 dir->FirstEnt = dp;
192         dir->LastEnt = dp;
193         
194         return 0;
195 }
196
197 int RAMDisk_Unlink(tVFS_Node *Node, const char *Name)
198 {
199         tRAMDisk_Dir    *dir = Node->ImplPtr;
200         tRAMDisk_DirEnt *dp, *p = NULL;
201
202         // TODO: Is locking needed?
203
204         for( dp = dir->FirstEnt; dp; p = dp, dp = dp->Next )
205         {
206                 if( strcmp(dp->Name, Name) == 0 )
207                         break ;
208         }
209         if( !dp )       return -1;
210         
211         RAMDisk_int_DerefFile( dp->Inode );
212
213         if( !p )
214                 dir->FirstEnt = dp->Next;
215         else
216                 p->Next = dp->Next;
217         if( dir->LastEnt == dp )
218                 dir->LastEnt = p;
219         free(dp);
220
221         return 0;
222 }
223
224 // --- Files ---
225 size_t RAMDisk_Read(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer)
226 {
227         tRAMDisk_File   *file = Node->ImplPtr;
228          int    page_ofs;
229         char    *page_virt;
230         size_t  rem;
231         
232         if( Offset >= file->Size )
233                 return 0;
234         
235         if( Offset + Size > file->Size )
236                 Size = file->Size - Size;
237
238         if( Size == 0 )
239                 return 0;
240
241         page_ofs = Offset / PAGE_SIZE;
242         Offset %= PAGE_SIZE;
243         rem = Size;
244
245         page_virt = _GetPage(file, page_ofs++);
246         if( Offset + Size <= PAGE_SIZE ) {
247                 memcpy(Buffer, page_virt + Offset, Size);
248                 return Size;
249         }
250         
251         memcpy(Buffer, page_virt + Offset, PAGE_SIZE - Offset);
252         Buffer += PAGE_SIZE - Offset;
253         rem -= PAGE_SIZE - Offset;
254         
255         while( rem >= PAGE_SIZE )
256         {
257                 _DropPage(page_virt);
258                 page_virt = _GetPage(file, page_ofs++);
259                 memcpy(Buffer, page_virt, PAGE_SIZE);
260                 Buffer += PAGE_SIZE;
261                 rem -= PAGE_SIZE;
262         }
263
264         if( rem > 0 )
265         {
266                 page_virt = _GetPage(file, page_ofs);
267                 memcpy(Buffer, page_virt, rem);
268         }
269
270         _DropPage(page_virt);
271         
272         return Size;
273 }
274
275 size_t RAMDisk_Write(tVFS_Node *Node, off_t Offset, size_t Size, const void *Buffer)
276 {
277         return 0;
278 }
279
280

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