PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
rpc_server.c
1#include <kernel.h>
2#include <malloc.h>
3#include <sifcmd.h>
4#include <sifrpc.h>
5#include <stdio.h>
6#include <errno.h>
7#include <string.h>
8#include <netman.h>
9#include <netman_rpc.h>
10
11#include "internal.h"
12#include "rpc_server.h"
13
14static int NETMAN_RpcSvr_threadID=-1, NETMAN_Rx_threadID=-1, SifHandlerID=-1;
15static unsigned char NETMAN_RpcSvr_ThreadStack[0x1000] ALIGNED(16);
16static unsigned char NETMAN_Rx_ThreadStack[0x1000] ALIGNED(16);
17static unsigned char IsInitialized=0, IsProcessingRx;
18
19static struct NetManBD *FrameBufferStatus = NULL;
20static struct NetManBD *RxIOPFrameBufferStatus;
21static unsigned short int RxBufferRdPtr, RxBufferNextRdPtr;
22extern void *_gp;
23
24static void NETMAN_RxThread(void *arg);
25
26static void ClearBufferLen(int index, void *packet, void *payload)
27{
28 struct NetManBD *bd;
30
31 bd = UNCACHED_SEG(&FrameBufferStatus[index]);
32 bd->length = 0;
33 bd->packet = packet;
34 bd->payload = payload;
35
36 //Transfer to IOP RAM
37 dmat.src = (void*)&FrameBufferStatus[index];
38 dmat.dest = &RxIOPFrameBufferStatus[index];
39 dmat.size = sizeof(struct NetManBD);
40 dmat.attr = 0;
41 while(SifSetDma(&dmat, 1) == 0){ };
42}
43
44static s32 HandleRxEvent(s32 channel)
45{
46 struct NetManBD *bd;
47
48 (void)channel;
49
50 bd = UNCACHED_SEG(&FrameBufferStatus[RxBufferNextRdPtr]);
51 if(bd->length > 0)
52 {
53 iSifSetDChain();
54
55 if(!IsProcessingRx)
56 {
57 IsProcessingRx = 1;
58 iWakeupThread(NETMAN_Rx_threadID);
59 }
60 }
61
62 ExitHandler();
63 //Must allow the other SIF handlers to check their states, as it is possible for this handler to block other handlers until FrameBufferStatus is cleared.
64 return 0;
65}
66
67int NetManRPCAllocRxBuffers(void)
68{
69 int i;
70
71 for(i = 0; i < NETMAN_RPC_BLOCK_SIZE; i++)
72 {
73 void *packet, *payload;
74
75 if((packet = NetManNetProtStackAllocRxPacket(NETMAN_NETIF_FRAME_SIZE, &payload)) != NULL)
76 {
77 ClearBufferLen(i, packet, payload);
78 } else {
79 printf("NETMAN: error - unable to allocate Rx FIFO buffers.\n");
80 return -ENOMEM;
81 }
82 }
83
84 return 0;
85}
86
87/* Main EE RPC thread. */
88static void *NETMAN_EE_RPC_Handler(int fnum, void *buffer, int NumBytes)
89{
91 void *result;
92
93 (void)NumBytes;
94
95 switch(fnum)
96 {
97 case NETMAN_EE_RPC_FUNC_INIT:
98 RxIOPFrameBufferStatus = *(void**)buffer;
99
100 //Maintain 64-byte alignment to avoid non-uncached writes to the same cache line from contaminating the line.
101 if(FrameBufferStatus == NULL) FrameBufferStatus = memalign(64, sizeof(struct NetManBD) * NETMAN_RPC_BLOCK_SIZE);
102
103 if(FrameBufferStatus != NULL)
104 {
105 memset(UNCACHED_SEG(FrameBufferStatus), 0, sizeof(struct NetManBD) * NETMAN_RPC_BLOCK_SIZE);
106 RxBufferRdPtr = 0;
107 RxBufferNextRdPtr = 0;
108 IsProcessingRx = 0;
109
110 thread.func=&NETMAN_RxThread;
111 thread.stack=NETMAN_Rx_ThreadStack;
112 thread.stack_size=sizeof(NETMAN_Rx_ThreadStack);
113 thread.gp_reg=&_gp;
114 thread.initial_priority=0x59; /* Should be given a lower priority than the protocol stack, so that the protocol stack can process incoming frames. */
115 thread.attr=thread.option=0;
116
117 if((NETMAN_Rx_threadID=CreateThread(&thread)) >= 0)
118 {
119 StartThread(NETMAN_Rx_threadID, NULL);
120
121 SifHandlerID = AddDmacHandler(DMAC_SIF0, &HandleRxEvent, 0);
122 EnableDmac(DMAC_SIF0);
123 ((struct NetManEEInitResult *)buffer)->result = 0;
124 ((struct NetManEEInitResult *)buffer)->FrameBufferStatus = FrameBufferStatus;
125 }
126 else{
127 ((struct NetManEEInitResult *)buffer)->result = NETMAN_Rx_threadID;
128 }
129 }else{
130 ((struct NetManEEInitResult *)buffer)->result = -ENOMEM;
131 }
132 result=buffer;
133 break;
134 case NETMAN_EE_RPC_FUNC_DEINIT:
135 if(FrameBufferStatus != NULL)
136 {
137 free(FrameBufferStatus);
138 FrameBufferStatus = NULL;
139 }
140 result=NULL;
141 break;
142 case NETMAN_EE_RPC_FUNC_HANDLE_LINK_STATUS_CHANGE:
143 NetManToggleGlobalNetIFLinkState(*(u32*)buffer);
144 result=NULL;
145 break;
146 default:
147 printf("NETMAN [EE]: Unrecognized command: 0x%x\n", fnum);
148 *(int *)buffer=EINVAL;
149 result=buffer;
150 }
151
152 return result;
153}
154
155static struct t_SifRpcDataQueue cb_queue;
156static struct t_SifRpcServerData cb_srv;
157
158static void NETMAN_RPC_Thread(void *arg)
159{
160 static unsigned char cb_rpc_buffer[64] __attribute__((__aligned__(64)));
161
162 (void)arg;
163
164 SifSetRpcQueue(&cb_queue, NETMAN_RpcSvr_threadID);
165 SifRegisterRpc(&cb_srv, NETMAN_RPC_NUMBER, &NETMAN_EE_RPC_Handler, cb_rpc_buffer, NULL, NULL, &cb_queue);
166 SifRpcLoop(&cb_queue);
167}
168
169static void NETMAN_RxThread(void *arg)
170{
171 volatile struct NetManBD *bd;
172 u32 PacketLength, PacketLengthAligned;
173 u8 run;
174
175 (void)arg;
176
177 while(1)
178 {
179 void *payload, *payloadNext;
180 void *packet, *packetNext;
181
182 bd = UNCACHED_SEG(&FrameBufferStatus[RxBufferRdPtr]);
183
184 do {
185 DI();
186 PacketLength = bd->length;
187 if (PacketLength > 0)
188 {
189 run = 1;
190 } else {
191 run = 0;
192 IsProcessingRx = 0;
193 }
194 EI();
195
196 if(!run)
197 SleepThread();
198 } while(!run);
199
200 payload = bd->payload;
201 packet = bd->packet;
202
203 //Must successfully allocate a replacement buffer for the input buffer.
204 while((packetNext = NetManNetProtStackAllocRxPacket(NETMAN_NETIF_FRAME_SIZE, &payloadNext)) == NULL){};
205 RxBufferNextRdPtr = (RxBufferNextRdPtr + 1) % NETMAN_RPC_BLOCK_SIZE;
206 ClearBufferLen(RxBufferRdPtr, packetNext, payloadNext);
207
208 //Increment read pointer by one place.
209 RxBufferRdPtr = RxBufferNextRdPtr;
210
211 //Now process the received packet.
212 PacketLengthAligned = (PacketLength + 63) & ~63;
213 SifWriteBackDCache(payload, PacketLengthAligned);
214 NetManNetProtStackReallocRxPacket(packet, PacketLength);
215 NetManNetProtStackEnQRxPacket(packet);
216 }
217}
218
219int NetManInitRPCServer(void)
220{
221 int result;
222 ee_thread_t ThreadData;
223
224 if(!IsInitialized)
225 {
226 ThreadData.func=&NETMAN_RPC_Thread;
227 ThreadData.stack=NETMAN_RpcSvr_ThreadStack;
228 ThreadData.stack_size=sizeof(NETMAN_RpcSvr_ThreadStack);
229 ThreadData.gp_reg=&_gp;
230 ThreadData.initial_priority=0x57; /* The RPC server thread should be given a higher priority than the protocol stack, so that it can issue commants to the EE and return. */
231 ThreadData.attr=ThreadData.option=0;
232
233 if((NETMAN_RpcSvr_threadID=CreateThread(&ThreadData))>=0)
234 {
235 StartThread(NETMAN_RpcSvr_threadID, NULL);
236 IsInitialized=1;
237 result=0;
238 }
239 else result=NETMAN_RpcSvr_threadID;
240 }
241 else result=0;
242
243 return result;
244}
245
246void NetManDeinitRPCServer(void)
247{
248 if(IsInitialized)
249 {
250 SifRemoveRpc(&cb_srv, &cb_queue);
251 SifRemoveRpcQueue(&cb_queue);
252 RemoveDmacHandler(DMAC_SIF0, SifHandlerID);
253
254 if(NETMAN_RpcSvr_threadID>=0)
255 {
256 TerminateThread(NETMAN_RpcSvr_threadID);
257 DeleteThread(NETMAN_RpcSvr_threadID);
258 NETMAN_RpcSvr_threadID = -1;
259 }
260
261 if(NETMAN_Rx_threadID>=0)
262 {
263 TerminateThread(NETMAN_Rx_threadID);
264 DeleteThread(NETMAN_Rx_threadID);
265 NETMAN_Rx_threadID = -1;
266 }
267
268 IsInitialized=0;
269 }
270}
#define EINVAL
Definition errno.h:63
#define ENOMEM
Definition errno.h:43