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 int FIFO_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX]);
30 tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename);
31 tVFS_Node *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_Unlink(tVFS_Node *Node, const char *OldName);
35 size_t FIFO_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
36 size_t FIFO_Write(tVFS_Node *Node, off_t Offset, size_t 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 .Unlink = FIFO_Unlink,
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 int FIFO_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX])
97 tPipe *tmp = gFIFO_NamedPipes;
99 // Entry 0 is Anon Pipes
101 strcpy(Dest, "anon");
105 // Find the id'th node
106 while(--Id && tmp) tmp = tmp->Next;
107 // If the list ended, error return
111 strncpy(Dest, tmp->Name, FILENAME_MAX);
116 * \fn tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename)
117 * \brief Find a file in the FIFO root
118 * \note Creates an anon pipe if anon is requested
120 tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename)
123 if(!Filename) return NULL;
126 if(Filename[0] == '\0') return NULL;
129 if(Filename[0] == 'a' && Filename[1] == 'n'
130 && Filename[2] == 'o' && Filename[3] == 'n'
131 && Filename[4] == '\0') {
132 tmp = FIFO_Int_NewPipe(DEFAULT_RING_SIZE, "anon");
137 tmp = gFIFO_NamedPipes;
140 if(strcmp(tmp->Name, Filename) == 0)
148 * \fn int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
150 tVFS_Node *FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
155 void FIFO_Reference(tVFS_Node *Node)
157 if(!Node->ImplPtr) return ;
159 Node->ReferenceCount ++;
163 * \fn void FIFO_Close(tVFS_Node *Node)
164 * \brief Close a FIFO end
166 void FIFO_Close(tVFS_Node *Node)
169 if(!Node->ImplPtr) return ;
171 Node->ReferenceCount --;
172 if(Node->ReferenceCount) return ;
174 pipe = Node->ImplPtr;
176 if(strcmp(pipe->Name, "anon") == 0) {
177 Log_Debug("FIFO", "Pipe %p closed", Node->ImplPtr);
186 * \brief Delete a pipe
188 int FIFO_Unlink(tVFS_Node *Node, const char *OldName)
192 if(Node != &gFIFO_DriverInfo.RootNode) return 0;
195 if(strcmp(OldName, "anon")) return 0;
198 for(pipe = gFIFO_NamedPipes;
202 if(strcmp(pipe->Name, OldName) == 0)
217 * \brief Read from a fifo pipe
219 size_t FIFO_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
221 tPipe *pipe = Node->ImplPtr;
223 Uint remaining = Length;
227 ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
231 // Wait for buffer to fill
232 if(pipe->Flags & PF_BLOCKING)
234 if( pipe->ReadPos == pipe->WritePos )
235 VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "FIFO_Read");
240 if(pipe->ReadPos == pipe->WritePos)
242 VFS_MarkAvaliable(Node, 0);
249 if( pipe->ReadPos < pipe->WritePos )
251 int avail_bytes = pipe->WritePos - pipe->ReadPos;
252 if( avail_bytes < remaining ) len = avail_bytes;
256 int avail_bytes = pipe->WritePos + pipe->BufSize - pipe->ReadPos;
257 if( avail_bytes < remaining ) len = avail_bytes;
260 LOG("len = %i, remaining = %i", len, remaining);
262 // Check if read overflows buffer
263 if(len > pipe->BufSize - pipe->ReadPos)
265 int ofs = pipe->BufSize - pipe->ReadPos;
266 memcpy(Buffer, &pipe->Buffer[pipe->ReadPos], ofs);
267 memcpy((Uint8*)Buffer + ofs, &pipe->Buffer, len-ofs);
271 memcpy(Buffer, &pipe->Buffer[pipe->ReadPos], len);
274 // Increment read position
275 pipe->ReadPos += len;
276 pipe->ReadPos %= pipe->BufSize;
279 if( pipe->ReadPos == pipe->WritePos ) {
280 VFS_MarkAvaliable(Node, 0);
282 VFS_MarkFull(Node, 0); // Buffer can't still be full
284 // Decrement Remaining Bytes
286 // Increment Buffer address
287 Buffer = (Uint8*)Buffer + len;
289 // TODO: Option to read differently
300 * \brief Write to a fifo pipe
302 size_t FIFO_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
304 tPipe *pipe = Node->ImplPtr;
306 Uint remaining = Length;
310 ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
314 // Wait for buffer to empty
315 if(pipe->Flags & PF_BLOCKING) {
316 if( pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize )
317 VFS_SelectNode(Node, VFS_SELECT_WRITE, NULL, "FIFO_Write");
320 if( pipe->ReadPos > pipe->WritePos )
322 int rem_space = pipe->ReadPos - pipe->WritePos;
323 if(rem_space < remaining) len = rem_space;
327 int rem_space = pipe->ReadPos + pipe->BufSize - pipe->WritePos;
328 if(rem_space < remaining) len = rem_space;
333 if(pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize)
339 if(pipe->ReadPos - pipe->WritePos < remaining)
340 len = pipe->ReadPos - pipe->WritePos;
345 // Check if write overflows buffer
346 if(len > pipe->BufSize - pipe->WritePos)
348 int ofs = pipe->BufSize - pipe->WritePos;
349 memcpy(&pipe->Buffer[pipe->WritePos], Buffer, ofs);
350 memcpy(&pipe->Buffer, (Uint8*)Buffer + ofs, len-ofs);
354 memcpy(&pipe->Buffer[pipe->WritePos], Buffer, len);
357 // Increment read position
358 pipe->WritePos += len;
359 pipe->WritePos %= pipe->BufSize;
362 if( pipe->ReadPos == pipe->WritePos ) {
363 VFS_MarkFull(Node, 1); // Buffer full
365 VFS_MarkAvaliable(Node, 1);
367 // Decrement Remaining Bytes
369 // Increment Buffer address
370 Buffer = (Uint8*)Buffer + len;
379 * \fn tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
380 * \brief Create a new pipe
382 tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
385 int namelen = strlen(Name) + 1;
386 int allocsize = sizeof(tPipe) + sizeof(tVFS_ACL) + Size + namelen;
388 ret = calloc(1, allocsize);
389 if(!ret) return NULL;
392 ret->Flags = PF_BLOCKING;
396 ret->Buffer = (void*)( (Uint)ret + sizeof(tPipe) + sizeof(tVFS_ACL) );
398 // Set name (and FIFO name)
399 ret->Name = ret->Buffer + Size;
400 strcpy(ret->Name, Name);
401 // - Start empty, max of `Size`
402 //Semaphore_Init( &ret->Semaphore, 0, Size, "FIFO", ret->Name );
405 ret->Node.ReferenceCount = 1;
407 ret->Node.ImplPtr = ret;
408 ret->Node.UID = Threads_GetUID();
409 ret->Node.GID = Threads_GetGID();
410 ret->Node.NumACLs = 1;
411 ret->Node.ACLs = (void*)( (Uint)ret + sizeof(tPipe) );
412 ret->Node.ACLs->Group = 0;
413 ret->Node.ACLs->ID = ret->Node.UID;
414 ret->Node.ACLs->Inv = 0;
415 ret->Node.ACLs->Perms = -1;
418 = ret->Node.ATime = now();
419 ret->Node.Type = &gFIFO_PipeNodeType;