9 #define DEFAULT_RING_SIZE 2048
13 typedef struct sPipe {
25 int FIFO_Install(char **Arguments);
26 int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data);
27 char *FIFO_ReadDir(tVFS_Node *Node, int Id);
28 tVFS_Node *FIFO_FindDir(tVFS_Node *Node, char *Filename);
29 int FIFO_MkNod(tVFS_Node *Node, char *Name, Uint Flags);
30 void FIFO_Close(tVFS_Node *Node);
31 int FIFO_Relink(tVFS_Node *Node, char *OldName, char *NewName);
32 Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
33 Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
34 tPipe *FIFO_Int_NewPipe(int Size, char *Name);
37 MODULE_DEFINE(0, 0x0032, FIFO, FIFO_Install, NULL, NULL);
38 tDevFS_Driver gFIFO_DriverInfo = {
42 .ACLs = &gVFS_ACL_EveryoneRW,
43 .Flags = VFS_FFLAG_DIRECTORY,
44 .ReadDir = FIFO_ReadDir,
45 .FindDir = FIFO_FindDir,
47 .Relink = FIFO_Relink,
51 tVFS_Node gFIFO_AnonNode = {
53 .ACLs = &gVFS_ACL_EveryoneRW,
55 tPipe *gFIFO_NamedPipes = NULL;
59 * \fn int FIFO_Install(char **Options)
60 * \brief Installs the FIFO Driver
62 int FIFO_Install(char **Options)
64 DevFS_AddDevice( &gFIFO_DriverInfo );
69 * \fn int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data)
71 int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data)
77 * \fn char *FIFO_ReadDir(tVFS_Node *Node, int Id)
78 * \brief Reads from the FIFO root
80 char *FIFO_ReadDir(tVFS_Node *Node, int Id)
82 tPipe *tmp = gFIFO_NamedPipes;
83 // Entry 0 is Anon Pipes
84 if(Id == 0) return strdup("anon");
86 // Find the id'th node
87 while(--Id && tmp) tmp = tmp->Next;
88 // If node found, return it
89 if(tmp) return strdup(tmp->Name);
95 * \fn tVFS_Node *FIFO_FindDir(tVFS_Node *Node, char *Filename)
96 * \brief Find a file in the FIFO root
97 * \note Creates an anon pipe if anon is requested
99 tVFS_Node *FIFO_FindDir(tVFS_Node *Node, char *Filename)
102 if(!Filename) return NULL;
105 if(Filename[0] == '\0') return NULL;
108 if(Filename[0] == 'a' && Filename[1] == 'n'
109 && Filename[2] == 'o' && Filename[3] == 'n'
110 && Filename[4] == '\0') {
111 tmp = FIFO_Int_NewPipe(DEFAULT_RING_SIZE, "anon");
116 tmp = gFIFO_NamedPipes;
119 if(strcmp(tmp->Name, Filename) == 0)
127 * \fn int FIFO_MkNod(tVFS_Node *Node, char *Name, Uint Flags)
129 int FIFO_MkNod(tVFS_Node *Node, char *Name, Uint Flags)
135 * \fn void FIFO_Close(tVFS_Node *Node)
136 * \brief Close a FIFO end
138 void FIFO_Close(tVFS_Node *Node)
141 if(!Node->ImplPtr) return ;
143 Node->ReferenceCount --;
144 if(Node->ReferenceCount) return ;
146 pipe = Node->ImplPtr;
148 if(strcmp(pipe->Name, "anon") == 0) {
157 * \fn int FIFO_Relink(tVFS_Node *Node, char *OldName, char *NewName)
158 * \brief Relink a file (Deletes named pipes)
160 int FIFO_Relink(tVFS_Node *Node, char *OldName, char *NewName)
164 if(Node != &gFIFO_DriverInfo.RootNode) return 0;
167 if(strcmp(OldName, "anon")) return 0;
170 for(pipe = gFIFO_NamedPipes;
174 if(strcmp(pipe->Name, OldName) == 0)
179 // Relink a named pipe
182 for(tmp = gFIFO_NamedPipes;
186 if(strcmp(tmp->Name, NewName) == 0) return 0;
190 pipe->Name = malloc(strlen(NewName)+1);
191 strcpy(pipe->Name, NewName);
205 * \fn Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
206 * \brief Read from a fifo pipe
208 Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
210 tPipe *pipe = Node->ImplPtr;
212 Uint remaining = Length;
218 // Wait for buffer to fill
219 if(pipe->Flags & PF_BLOCKING)
220 while(pipe->ReadPos == pipe->WritePos)
223 if(pipe->ReadPos == pipe->WritePos)
227 if(pipe->WritePos - pipe->ReadPos < remaining)
228 len = pipe->WritePos - pipe->ReadPos;
232 // Check if read overflows buffer
233 if(len > pipe->BufSize - pipe->ReadPos)
235 int ofs = pipe->BufSize - pipe->ReadPos;
236 memcpy(Buffer, &pipe->Buffer[pipe->ReadPos], ofs);
237 memcpy(Buffer + ofs, &pipe->Buffer, len-ofs);
241 memcpy(Buffer, &pipe->Buffer[pipe->ReadPos], len);
244 // Increment read position
245 pipe->ReadPos += len;
246 pipe->ReadPos %= pipe->BufSize;
248 // Decrement Remaining Bytes
250 // Increment Buffer address
259 * \fn Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
260 * \brief Write to a fifo pipe
262 Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
264 tPipe *pipe = Node->ImplPtr;
266 Uint remaining = Length;
272 // Wait for buffer to empty
273 if(pipe->Flags & PF_BLOCKING)
274 while(pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize)
277 if(pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize)
281 if(pipe->ReadPos - pipe->WritePos < remaining)
282 len = pipe->ReadPos - pipe->WritePos;
286 // Check if write overflows buffer
287 if(len > pipe->BufSize - pipe->WritePos)
289 int ofs = pipe->BufSize - pipe->WritePos;
290 memcpy(&pipe->Buffer[pipe->WritePos], Buffer, ofs);
291 memcpy(&pipe->Buffer, Buffer + ofs, len-ofs);
295 memcpy(&pipe->Buffer[pipe->WritePos], Buffer, len);
298 // Increment read position
299 pipe->WritePos += len;
300 pipe->WritePos %= pipe->BufSize;
302 // Decrement Remaining Bytes
304 // Increment Buffer address
313 * \fn tPipe *FIFO_Int_NewPipe(int Size, char *Name)
314 * \brief Create a new pipe
316 tPipe *FIFO_Int_NewPipe(int Size, char *Name)
319 int allocsize = sizeof(tPipe) + sizeof(tVFS_ACL) + Size;
321 ret = malloc(allocsize);
322 if(!ret) return NULL;
325 memset(ret, 0, allocsize);
331 ret->Buffer = (void*)( (Uint)ret + sizeof(tPipe) + sizeof(tVFS_ACL) );
339 ret->Node.ImplPtr = ret;
340 ret->Node.UID = Threads_GetUID();
341 ret->Node.GID = Threads_GetGID();
342 ret->Node.NumACLs = 1;
343 ret->Node.ACLs = (void*)( (Uint)ret + sizeof(tPipe) );
344 ret->Node.ACLs->Group = 0;
345 ret->Node.ACLs->ID = ret->Node.UID;
346 ret->Node.ACLs->Inv = 0;
347 ret->Node.ACLs->Perms = -1;
350 = ret->Node.ATime = now();
351 ret->Node.Read = FIFO_Read;
352 ret->Node.Write = FIFO_Write;
353 ret->Node.Close = FIFO_Close;