10 #define DEFAULT_RING_SIZE 2048
14 typedef struct sPipe {
26 int FIFO_Install(char **Arguments);
27 int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data);
28 char *FIFO_ReadDir(tVFS_Node *Node, int Id);
29 tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename);
30 int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
31 void FIFO_Close(tVFS_Node *Node);
32 int FIFO_Relink(tVFS_Node *Node, const char *OldName, const char *NewName);
33 Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
34 Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer);
35 tPipe *FIFO_Int_NewPipe(int Size, const char *Name);
38 MODULE_DEFINE(0, 0x0032, FIFO, FIFO_Install, NULL, NULL);
39 tVFS_NodeType gFIFO_DirNodeType = {
40 .TypeName = "FIFO Dir Node",
41 .ReadDir = FIFO_ReadDir,
42 .FindDir = FIFO_FindDir,
44 .Relink = FIFO_Relink,
47 tVFS_NodeType gFIFO_PipeNodeType = {
48 .TypeName = "FIFO Pipe Node",
53 tDevFS_Driver gFIFO_DriverInfo = {
58 .ACLs = &gVFS_ACL_EveryoneRW,
59 .Flags = VFS_FFLAG_DIRECTORY,
60 .Type = &gFIFO_DirNodeType
63 tVFS_Node gFIFO_AnonNode = {
65 .ACLs = &gVFS_ACL_EveryoneRW,
67 tPipe *gFIFO_NamedPipes = NULL;
71 * \fn int FIFO_Install(char **Options)
72 * \brief Installs the FIFO Driver
74 int FIFO_Install(char **Options)
76 DevFS_AddDevice( &gFIFO_DriverInfo );
81 * \fn int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data)
83 int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data)
89 * \fn char *FIFO_ReadDir(tVFS_Node *Node, int Id)
90 * \brief Reads from the FIFO root
92 char *FIFO_ReadDir(tVFS_Node *Node, int Id)
94 tPipe *tmp = gFIFO_NamedPipes;
96 // Entry 0 is Anon Pipes
97 if(Id == 0) return strdup("anon");
99 // Find the id'th node
100 while(--Id && tmp) tmp = tmp->Next;
101 // If node found, return it
102 if(tmp) return strdup(tmp->Name);
108 * \fn tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename)
109 * \brief Find a file in the FIFO root
110 * \note Creates an anon pipe if anon is requested
112 tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename)
115 if(!Filename) return NULL;
118 if(Filename[0] == '\0') return NULL;
121 if(Filename[0] == 'a' && Filename[1] == 'n'
122 && Filename[2] == 'o' && Filename[3] == 'n'
123 && Filename[4] == '\0') {
124 tmp = FIFO_Int_NewPipe(DEFAULT_RING_SIZE, "anon");
129 tmp = gFIFO_NamedPipes;
132 if(strcmp(tmp->Name, Filename) == 0)
140 * \fn int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
142 int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
148 * \fn void FIFO_Close(tVFS_Node *Node)
149 * \brief Close a FIFO end
151 void FIFO_Close(tVFS_Node *Node)
154 if(!Node->ImplPtr) return ;
156 Node->ReferenceCount --;
157 if(Node->ReferenceCount) return ;
159 pipe = Node->ImplPtr;
161 if(strcmp(pipe->Name, "anon") == 0) {
170 * \fn int FIFO_Relink(tVFS_Node *Node, const char *OldName, const char *NewName)
171 * \brief Relink a file (Deletes named pipes)
173 int FIFO_Relink(tVFS_Node *Node, const char *OldName, const char *NewName)
177 if(Node != &gFIFO_DriverInfo.RootNode) return 0;
180 if(strcmp(OldName, "anon")) return 0;
183 for(pipe = gFIFO_NamedPipes;
187 if(strcmp(pipe->Name, OldName) == 0)
192 // Relink a named pipe
195 for(tmp = gFIFO_NamedPipes;
199 if(strcmp(tmp->Name, NewName) == 0) return 0;
203 pipe->Name = malloc(strlen(NewName)+1);
204 strcpy(pipe->Name, NewName);
218 * \fn Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
219 * \brief Read from a fifo pipe
221 Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
223 tPipe *pipe = Node->ImplPtr;
225 Uint remaining = Length;
231 // Wait for buffer to fill
232 if(pipe->Flags & PF_BLOCKING)
235 len = Semaphore_Wait( &pipe->Semaphore, remaining );
237 VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "FIFO_Read");
239 // TODO: Rethink this, it might not work on buffer overflow
240 if(pipe->WritePos - pipe->ReadPos < remaining)
241 len = pipe->WritePos - pipe->ReadPos;
248 if(pipe->ReadPos == pipe->WritePos)
251 if(pipe->WritePos - pipe->ReadPos < remaining)
252 len = pipe->WritePos - pipe->ReadPos;
257 // Check if read overflows buffer
258 if(len > pipe->BufSize - pipe->ReadPos)
260 int ofs = pipe->BufSize - pipe->ReadPos;
261 memcpy(Buffer, &pipe->Buffer[pipe->ReadPos], ofs);
262 memcpy((Uint8*)Buffer + ofs, &pipe->Buffer, len-ofs);
266 memcpy(Buffer, &pipe->Buffer[pipe->ReadPos], len);
269 // Increment read position
270 pipe->ReadPos += len;
271 pipe->ReadPos %= pipe->BufSize;
274 if( pipe->ReadPos == pipe->WritePos ) {
275 VFS_MarkAvaliable(Node, 0);
277 VFS_MarkFull(Node, 0); // Buffer can't still be full
279 // Decrement Remaining Bytes
281 // Increment Buffer address
282 Buffer = (Uint8*)Buffer + len;
290 * \fn Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
291 * \brief Write to a fifo pipe
293 Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer)
295 tPipe *pipe = Node->ImplPtr;
297 Uint remaining = Length;
303 // Wait for buffer to empty
304 if(pipe->Flags & PF_BLOCKING) {
306 len = Semaphore_Signal( &pipe->Semaphore, remaining );
308 VFS_SelectNode(Node, VFS_SELECT_WRITE, NULL, "FIFO_Write");
309 if(pipe->ReadPos - pipe->WritePos < remaining)
310 len = pipe->ReadPos - pipe->WritePos;
317 if(pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize)
320 if(pipe->ReadPos - pipe->WritePos < remaining)
321 len = pipe->ReadPos - pipe->WritePos;
326 // Check if write overflows buffer
327 if(len > pipe->BufSize - pipe->WritePos)
329 int ofs = pipe->BufSize - pipe->WritePos;
330 memcpy(&pipe->Buffer[pipe->WritePos], Buffer, ofs);
331 memcpy(&pipe->Buffer, (Uint8*)Buffer + ofs, len-ofs);
335 memcpy(&pipe->Buffer[pipe->WritePos], Buffer, len);
338 // Increment read position
339 pipe->WritePos += len;
340 pipe->WritePos %= pipe->BufSize;
343 if( pipe->ReadPos == pipe->WritePos ) {
344 VFS_MarkFull(Node, 1); // Buffer full
346 VFS_MarkAvaliable(Node, 1);
348 // Decrement Remaining Bytes
350 // Increment Buffer address
351 Buffer = (Uint8*)Buffer + len;
359 * \fn tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
360 * \brief Create a new pipe
362 tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
365 int namelen = strlen(Name) + 1;
366 int allocsize = sizeof(tPipe) + sizeof(tVFS_ACL) + Size + namelen;
368 ret = malloc(allocsize);
369 if(!ret) return NULL;
372 memset(ret, 0, allocsize);
373 ret->Flags = PF_BLOCKING;
377 ret->Buffer = (void*)( (Uint)ret + sizeof(tPipe) + sizeof(tVFS_ACL) );
379 // Set name (and FIFO name)
380 ret->Name = ret->Buffer + Size;
381 strcpy(ret->Name, Name);
382 // - Start empty, max of `Size`
383 //Semaphore_Init( &ret->Semaphore, 0, Size, "FIFO", ret->Name );
387 ret->Node.ImplPtr = ret;
388 ret->Node.UID = Threads_GetUID();
389 ret->Node.GID = Threads_GetGID();
390 ret->Node.NumACLs = 1;
391 ret->Node.ACLs = (void*)( (Uint)ret + sizeof(tPipe) );
392 ret->Node.ACLs->Group = 0;
393 ret->Node.ACLs->ID = ret->Node.UID;
394 ret->Node.ACLs->Inv = 0;
395 ret->Node.ACLs->Perms = -1;
398 = ret->Node.ATime = now();
399 ret->Node.Type = &gFIFO_PipeNodeType;