11 #define DEFAULT_RING_SIZE 2048
15 typedef struct sPipe {
27 int FIFO_Install(char **Arguments);
28 int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data);
29 char *FIFO_ReadDir(tVFS_Node *Node, int Id);
30 tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename);
31 int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
32 void FIFO_Reference(tVFS_Node *Node);
33 void FIFO_Close(tVFS_Node *Node);
34 int FIFO_Relink(tVFS_Node *Node, const char *OldName, const char *NewName);
35 Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
36 Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer);
37 tPipe *FIFO_Int_NewPipe(int Size, const char *Name);
40 MODULE_DEFINE(0, 0x0032, FIFO, FIFO_Install, NULL, NULL);
41 tVFS_NodeType gFIFO_DirNodeType = {
42 .TypeName = "FIFO Dir Node",
43 .ReadDir = FIFO_ReadDir,
44 .FindDir = FIFO_FindDir,
46 .Relink = FIFO_Relink,
49 tVFS_NodeType gFIFO_PipeNodeType = {
50 .TypeName = "FIFO Pipe Node",
54 .Reference = FIFO_Reference
56 tDevFS_Driver gFIFO_DriverInfo = {
61 .ACLs = &gVFS_ACL_EveryoneRW,
62 .Flags = VFS_FFLAG_DIRECTORY,
63 .Type = &gFIFO_DirNodeType
66 tVFS_Node gFIFO_AnonNode = {
68 .ACLs = &gVFS_ACL_EveryoneRW,
70 tPipe *gFIFO_NamedPipes = NULL;
74 * \fn int FIFO_Install(char **Options)
75 * \brief Installs the FIFO Driver
77 int FIFO_Install(char **Options)
79 DevFS_AddDevice( &gFIFO_DriverInfo );
84 * \fn int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data)
86 int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data)
92 * \fn char *FIFO_ReadDir(tVFS_Node *Node, int Id)
93 * \brief Reads from the FIFO root
95 char *FIFO_ReadDir(tVFS_Node *Node, int Id)
97 tPipe *tmp = gFIFO_NamedPipes;
99 // Entry 0 is Anon Pipes
100 if(Id == 0) return strdup("anon");
102 // Find the id'th node
103 while(--Id && tmp) tmp = tmp->Next;
104 // If node found, return it
105 if(tmp) return strdup(tmp->Name);
111 * \fn tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename)
112 * \brief Find a file in the FIFO root
113 * \note Creates an anon pipe if anon is requested
115 tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename)
118 if(!Filename) return NULL;
121 if(Filename[0] == '\0') return NULL;
124 if(Filename[0] == 'a' && Filename[1] == 'n'
125 && Filename[2] == 'o' && Filename[3] == 'n'
126 && Filename[4] == '\0') {
127 tmp = FIFO_Int_NewPipe(DEFAULT_RING_SIZE, "anon");
132 tmp = gFIFO_NamedPipes;
135 if(strcmp(tmp->Name, Filename) == 0)
143 * \fn int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
145 int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
150 void FIFO_Reference(tVFS_Node *Node)
152 if(!Node->ImplPtr) return ;
154 Node->ReferenceCount ++;
158 * \fn void FIFO_Close(tVFS_Node *Node)
159 * \brief Close a FIFO end
161 void FIFO_Close(tVFS_Node *Node)
164 if(!Node->ImplPtr) return ;
166 Node->ReferenceCount --;
167 if(Node->ReferenceCount) return ;
169 pipe = Node->ImplPtr;
171 if(strcmp(pipe->Name, "anon") == 0) {
172 Log_Debug("FIFO", "Pipe %p closed", Node->ImplPtr);
181 * \fn int FIFO_Relink(tVFS_Node *Node, const char *OldName, const char *NewName)
182 * \brief Relink a file (Deletes named pipes)
184 int FIFO_Relink(tVFS_Node *Node, const char *OldName, const char *NewName)
188 if(Node != &gFIFO_DriverInfo.RootNode) return 0;
191 if(strcmp(OldName, "anon")) return 0;
194 for(pipe = gFIFO_NamedPipes;
198 if(strcmp(pipe->Name, OldName) == 0)
203 // Relink a named pipe
206 for(tmp = gFIFO_NamedPipes;
210 if(strcmp(tmp->Name, NewName) == 0) return 0;
214 pipe->Name = malloc(strlen(NewName)+1);
215 strcpy(pipe->Name, NewName);
229 * \fn Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
230 * \brief Read from a fifo pipe
232 Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
234 tPipe *pipe = Node->ImplPtr;
236 Uint remaining = Length;
240 ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
244 // Wait for buffer to fill
245 if(pipe->Flags & PF_BLOCKING)
247 if( pipe->ReadPos == pipe->WritePos )
248 VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "FIFO_Read");
253 if(pipe->ReadPos == pipe->WritePos)
255 VFS_MarkAvaliable(Node, 0);
262 if( pipe->ReadPos < pipe->WritePos )
264 int avail_bytes = pipe->WritePos - pipe->ReadPos;
265 if( avail_bytes < remaining ) len = avail_bytes;
269 int avail_bytes = pipe->WritePos + pipe->BufSize - pipe->ReadPos;
270 if( avail_bytes < remaining ) len = avail_bytes;
273 LOG("len = %i, remaining = %i", len, remaining);
275 // Check if read overflows buffer
276 if(len > pipe->BufSize - pipe->ReadPos)
278 int ofs = pipe->BufSize - pipe->ReadPos;
279 memcpy(Buffer, &pipe->Buffer[pipe->ReadPos], ofs);
280 memcpy((Uint8*)Buffer + ofs, &pipe->Buffer, len-ofs);
284 memcpy(Buffer, &pipe->Buffer[pipe->ReadPos], len);
287 // Increment read position
288 pipe->ReadPos += len;
289 pipe->ReadPos %= pipe->BufSize;
292 if( pipe->ReadPos == pipe->WritePos ) {
293 VFS_MarkAvaliable(Node, 0);
295 VFS_MarkFull(Node, 0); // Buffer can't still be full
297 // Decrement Remaining Bytes
299 // Increment Buffer address
300 Buffer = (Uint8*)Buffer + len;
302 // TODO: Option to read differently
313 * \fn Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
314 * \brief Write to a fifo pipe
316 Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer)
318 tPipe *pipe = Node->ImplPtr;
320 Uint remaining = Length;
324 ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
328 // Wait for buffer to empty
329 if(pipe->Flags & PF_BLOCKING) {
330 if( pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize )
331 VFS_SelectNode(Node, VFS_SELECT_WRITE, NULL, "FIFO_Write");
334 if( pipe->ReadPos > pipe->WritePos )
336 int rem_space = pipe->ReadPos - pipe->WritePos;
337 if(rem_space < remaining) len = rem_space;
341 int rem_space = pipe->ReadPos + pipe->BufSize - pipe->WritePos;
342 if(rem_space < remaining) len = rem_space;
347 if(pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize)
353 if(pipe->ReadPos - pipe->WritePos < remaining)
354 len = pipe->ReadPos - pipe->WritePos;
359 // Check if write overflows buffer
360 if(len > pipe->BufSize - pipe->WritePos)
362 int ofs = pipe->BufSize - pipe->WritePos;
363 memcpy(&pipe->Buffer[pipe->WritePos], Buffer, ofs);
364 memcpy(&pipe->Buffer, (Uint8*)Buffer + ofs, len-ofs);
368 memcpy(&pipe->Buffer[pipe->WritePos], Buffer, len);
371 // Increment read position
372 pipe->WritePos += len;
373 pipe->WritePos %= pipe->BufSize;
376 if( pipe->ReadPos == pipe->WritePos ) {
377 VFS_MarkFull(Node, 1); // Buffer full
379 VFS_MarkAvaliable(Node, 1);
381 // Decrement Remaining Bytes
383 // Increment Buffer address
384 Buffer = (Uint8*)Buffer + len;
393 * \fn tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
394 * \brief Create a new pipe
396 tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
399 int namelen = strlen(Name) + 1;
400 int allocsize = sizeof(tPipe) + sizeof(tVFS_ACL) + Size + namelen;
402 ret = calloc(1, allocsize);
403 if(!ret) return NULL;
406 ret->Flags = PF_BLOCKING;
410 ret->Buffer = (void*)( (Uint)ret + sizeof(tPipe) + sizeof(tVFS_ACL) );
412 // Set name (and FIFO name)
413 ret->Name = ret->Buffer + Size;
414 strcpy(ret->Name, Name);
415 // - Start empty, max of `Size`
416 //Semaphore_Init( &ret->Semaphore, 0, Size, "FIFO", ret->Name );
419 ret->Node.ReferenceCount = 1;
421 ret->Node.ImplPtr = ret;
422 ret->Node.UID = Threads_GetUID();
423 ret->Node.GID = Threads_GetGID();
424 ret->Node.NumACLs = 1;
425 ret->Node.ACLs = (void*)( (Uint)ret + sizeof(tPipe) );
426 ret->Node.ACLs->Group = 0;
427 ret->Node.ACLs->ID = ret->Node.UID;
428 ret->Node.ACLs->Inv = 0;
429 ret->Node.ACLs->Perms = -1;
432 = ret->Node.ATime = now();
433 ret->Node.Type = &gFIFO_PipeNodeType;