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_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 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 * \brief Delete a pipe
183 int FIFO_Unlink(tVFS_Node *Node, const char *OldName)
187 if(Node != &gFIFO_DriverInfo.RootNode) return 0;
190 if(strcmp(OldName, "anon")) return 0;
193 for(pipe = gFIFO_NamedPipes;
197 if(strcmp(pipe->Name, OldName) == 0)
212 * \brief Read from a fifo pipe
214 size_t FIFO_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
216 tPipe *pipe = Node->ImplPtr;
218 Uint remaining = Length;
222 ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
226 // Wait for buffer to fill
227 if(pipe->Flags & PF_BLOCKING)
229 if( pipe->ReadPos == pipe->WritePos )
230 VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "FIFO_Read");
235 if(pipe->ReadPos == pipe->WritePos)
237 VFS_MarkAvaliable(Node, 0);
244 if( pipe->ReadPos < pipe->WritePos )
246 int avail_bytes = pipe->WritePos - pipe->ReadPos;
247 if( avail_bytes < remaining ) len = avail_bytes;
251 int avail_bytes = pipe->WritePos + pipe->BufSize - pipe->ReadPos;
252 if( avail_bytes < remaining ) len = avail_bytes;
255 LOG("len = %i, remaining = %i", len, remaining);
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;
284 // TODO: Option to read differently
295 * \brief Write to a fifo pipe
297 size_t FIFO_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
299 tPipe *pipe = Node->ImplPtr;
301 Uint remaining = Length;
305 ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
309 // Wait for buffer to empty
310 if(pipe->Flags & PF_BLOCKING) {
311 if( pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize )
312 VFS_SelectNode(Node, VFS_SELECT_WRITE, NULL, "FIFO_Write");
315 if( pipe->ReadPos > pipe->WritePos )
317 int rem_space = pipe->ReadPos - pipe->WritePos;
318 if(rem_space < remaining) len = rem_space;
322 int rem_space = pipe->ReadPos + pipe->BufSize - pipe->WritePos;
323 if(rem_space < remaining) len = rem_space;
328 if(pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize)
334 if(pipe->ReadPos - pipe->WritePos < remaining)
335 len = pipe->ReadPos - pipe->WritePos;
340 // Check if write overflows buffer
341 if(len > pipe->BufSize - pipe->WritePos)
343 int ofs = pipe->BufSize - pipe->WritePos;
344 memcpy(&pipe->Buffer[pipe->WritePos], Buffer, ofs);
345 memcpy(&pipe->Buffer, (Uint8*)Buffer + ofs, len-ofs);
349 memcpy(&pipe->Buffer[pipe->WritePos], Buffer, len);
352 // Increment read position
353 pipe->WritePos += len;
354 pipe->WritePos %= pipe->BufSize;
357 if( pipe->ReadPos == pipe->WritePos ) {
358 VFS_MarkFull(Node, 1); // Buffer full
360 VFS_MarkAvaliable(Node, 1);
362 // Decrement Remaining Bytes
364 // Increment Buffer address
365 Buffer = (Uint8*)Buffer + len;
374 * \fn tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
375 * \brief Create a new pipe
377 tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
380 int namelen = strlen(Name) + 1;
381 int allocsize = sizeof(tPipe) + sizeof(tVFS_ACL) + Size + namelen;
383 ret = calloc(1, allocsize);
384 if(!ret) return NULL;
387 ret->Flags = PF_BLOCKING;
391 ret->Buffer = (void*)( (Uint)ret + sizeof(tPipe) + sizeof(tVFS_ACL) );
393 // Set name (and FIFO name)
394 ret->Name = ret->Buffer + Size;
395 strcpy(ret->Name, Name);
396 // - Start empty, max of `Size`
397 //Semaphore_Init( &ret->Semaphore, 0, Size, "FIFO", ret->Name );
400 ret->Node.ReferenceCount = 1;
402 ret->Node.ImplPtr = ret;
403 ret->Node.UID = Threads_GetUID();
404 ret->Node.GID = Threads_GetGID();
405 ret->Node.NumACLs = 1;
406 ret->Node.ACLs = (void*)( (Uint)ret + sizeof(tPipe) );
407 ret->Node.ACLs->Group = 0;
408 ret->Node.ACLs->ID = ret->Node.UID;
409 ret->Node.ACLs->Inv = 0;
410 ret->Node.ACLs->Perms = -1;
413 = ret->Node.ATime = now();
414 ret->Node.Type = &gFIFO_PipeNodeType;