PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
rpc_client.c
1#include <errno.h>
2#include <kernel.h>
3#include <sifrpc.h>
4#include <string.h>
5#include <malloc.h>
6#include <netman.h>
7#include <netman_rpc.h>
8
9#include "rpc_client.h"
10
11static SifRpcClientData_t NETMAN_rpc_cd;
12extern void *_gp;
13
14static union {
15 s32 mode;
16 struct NetManIoctl IoctlArgs;
17 char netifName[NETMAN_NETIF_NAME_MAX_LEN];
18 struct NetManRegNetworkStack NetStack;
19 u8 buffer[128];
20}TransmitBuffer ALIGNED(64);
21
22static union {
23 s32 result;
24 struct NetManRegNetworkStackResult NetStackResult;
25 struct NetManIoctlResult IoctlResult;
26 struct NetManQueryMainNetIFResult QueryMainNetIFResult;
27 u8 buffer[128];
28}ReceiveBuffer ALIGNED(64);
29
30static int NetManIOSemaID = -1, NETMAN_Tx_threadID = -1;
31static unsigned char NETMAN_Tx_ThreadStack[0x1000] ALIGNED(16);
32
33static unsigned short int IOPFrameBufferWrPtr;
34static u8 *IOPFrameBuffer = NULL; /* On the IOP side. */
35static struct NetManBD *IOPFrameBufferStatus = NULL;
36static struct NetManBD *FrameBufferStatus = NULL;
37
38static unsigned char IsInitialized=0, IsProcessingTx;
39
40static void deinitCleanup(void)
41{
42 if(NetManIOSemaID >= 0)
43 {
44 DeleteSema(NetManIOSemaID);
45 NetManIOSemaID = -1;
46 }
47 if(NETMAN_Tx_threadID >= 0)
48 {
49 TerminateThread(NETMAN_Tx_threadID);
50 DeleteThread(NETMAN_Tx_threadID);
51 NETMAN_Tx_threadID = -1;
52 }
53}
54
55static void NETMAN_TxThread(void *arg);
56
57int NetManInitRPCClient(void){
58 static const char NetManID[]="NetMan";
59 int result;
60 ee_sema_t SemaData;
62
63 if(!IsInitialized)
64 {
65 SemaData.max_count=1;
66 SemaData.init_count=1;
67 SemaData.option=(u32)NetManID;
68 SemaData.attr=0;
69 if((NetManIOSemaID=CreateSema(&SemaData)) < 0)
70 {
71 deinitCleanup();
72 return NetManIOSemaID;
73 }
74
75 thread.func=&NETMAN_TxThread;
76 thread.stack=NETMAN_Tx_ThreadStack;
77 thread.stack_size=sizeof(NETMAN_Tx_ThreadStack);
78 thread.gp_reg=&_gp;
79 thread.initial_priority=0x56; /* Should be given a higher priority than the protocol stack, so that it can dump frames in the EE and return. */
80 thread.attr=thread.option=0;
81
82 if((NETMAN_Tx_threadID=CreateThread(&thread)) >= 0)
83 {
84 IsProcessingTx = 0;
85 StartThread(NETMAN_Tx_threadID, NULL);
86 } else {
87 deinitCleanup();
88 return NETMAN_Tx_threadID;
89 }
90
91 while((SifBindRpc(&NETMAN_rpc_cd, NETMAN_RPC_NUMBER, 0)<0)||(NETMAN_rpc_cd.server==NULL))
92 nopdelay();
93
94 if((result=SifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_INIT, 0, NULL, 0, &ReceiveBuffer, sizeof(s32), NULL, NULL))>=0)
95 {
96 if((result=ReceiveBuffer.result) == 0)
97 IsInitialized=1;
98 else
99 deinitCleanup();
100 }else{
101 deinitCleanup();
102 }
103 }
104 else result=0;
105
106 return result;
107}
108
109int NetManRPCRegisterNetworkStack(void)
110{
111 int result;
112
113 WaitSema(NetManIOSemaID);
114
115 if(FrameBufferStatus == NULL) FrameBufferStatus = memalign(64, NETMAN_RPC_BLOCK_SIZE * sizeof(struct NetManBD));
116
117 if(FrameBufferStatus != NULL)
118 {
119 memset(UNCACHED_SEG(FrameBufferStatus), 0, NETMAN_RPC_BLOCK_SIZE * sizeof(struct NetManBD));
120 TransmitBuffer.NetStack.FrameBufferStatus = FrameBufferStatus;
121 IOPFrameBufferWrPtr = 0;
122
123 if((result=SifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_REG_NETWORK_STACK, 0, &TransmitBuffer, sizeof(struct NetManRegNetworkStack), &ReceiveBuffer, sizeof(struct NetManRegNetworkStackResult), NULL, NULL))>=0)
124 {
125 if((result=ReceiveBuffer.NetStackResult.result) == 0)
126 {
127 IOPFrameBuffer = ReceiveBuffer.NetStackResult.FrameBuffer;
128 IOPFrameBufferStatus = ReceiveBuffer.NetStackResult.FrameBufferStatus;
129 }
130 }
131 }
132 else
133 {
134 result = -ENOMEM;
135 }
136
137 SignalSema(NetManIOSemaID);
138
139 return result;
140}
141
142int NetManRPCUnregisterNetworkStack(void)
143{
144 int result;
145
146 WaitSema(NetManIOSemaID);
147
148 result=SifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_UNREG_NETWORK_STACK, 0, NULL, 0, NULL, 0, NULL, NULL);
149 IOPFrameBuffer = NULL;
150 IOPFrameBufferWrPtr = 0;
151
152 free(FrameBufferStatus);
153 FrameBufferStatus = NULL;
154
155 SignalSema(NetManIOSemaID);
156
157 return result;
158}
159
160void NetManDeinitRPCClient(void)
161{
162 if(IsInitialized)
163 {
164 WaitSema(NetManIOSemaID);
165
166 SifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_DEINIT, 0, NULL, 0, NULL, 0, NULL, NULL);
167 deinitCleanup();
168
169 IsInitialized=0;
170 }
171}
172
173int NetManRpcIoctl(unsigned int command, void *args, unsigned int args_len, void *output, unsigned int length)
174{
175 int result;
176 struct NetManIoctl *IoctlArgs=&TransmitBuffer.IoctlArgs;
177
178 WaitSema(NetManIOSemaID);
179
180 IoctlArgs->command=command;
181 memcpy(IoctlArgs->args, args, args_len);
182 IoctlArgs->args_len=args_len;
183 IoctlArgs->output=output;
184 IoctlArgs->length=length;
185
186 if((result=SifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_IOCTL, 0, &TransmitBuffer, sizeof(struct NetManIoctl), &ReceiveBuffer, sizeof(struct NetManIoctlResult), NULL, NULL))>=0)
187 {
188 result=ReceiveBuffer.IoctlResult.result;
189 memcpy(output, ReceiveBuffer.IoctlResult.output, length);
190 }
191
192 SignalSema(NetManIOSemaID);
193
194 return result;
195}
196
197static void NETMAN_TxThread(void *arg)
198{
199 static SifCmdHeader_t cmd ALIGNED(64);
200 SifDmaTransfer_t dmat[2];
201 struct NetManPktCmd *npcmd;
202 int dmat_id, unaligned, unalignedCache;
203 void *payload, *payloadAligned, *payloadCacheAligned;
204 volatile struct NetManBD *bd, *bdNext;
205
206 (void)arg;
207
208 while(1)
209 {
210 int length, NumTx;
211 SleepThread();
212
213 NumTx = 0;
214 while((length = NetManTxPacketNext(&payload)) > 0)
215 {
216 IsProcessingTx = 1;
217
218 //Write back D-cache, before performing a DMA transfer.
219 unaligned = (int)((u32)payload & 15);
220 unalignedCache = (int)((u32)payload & 63);
221 payloadAligned = (void*)((u32)payload & ~15);
222 payloadCacheAligned = (void*)((u32)payload & ~63);
223 SifWriteBackDCache(payloadCacheAligned, (length + unalignedCache + 63) & ~63);
224
225 do {
226 //Wait for a spot to be freed up.
227 bd = UNCACHED_SEG(&FrameBufferStatus[IOPFrameBufferWrPtr]);
228 while(bd->length != 0){}
229
230 //Transfer to IOP RAM
231 //Determine mode of transfer.
232 bdNext = UNCACHED_SEG(&FrameBufferStatus[(IOPFrameBufferWrPtr + 1) % NETMAN_RPC_BLOCK_SIZE]);
233 if((NumTx + 1) >= NETMAN_FRAME_GROUP_SIZE || bdNext->length == 0)
234 {
235 //Prepare SIFCMD packet
236 //Record the frame length.
237 npcmd = (struct NetManPktCmd*)&cmd.opt;
238 npcmd->length = length;
239 npcmd->offset = unaligned;
240 npcmd->id = IOPFrameBufferWrPtr;
241
242 while((dmat_id = SifSendCmd(NETMAN_SIFCMD_ID, &cmd, sizeof(SifCmdHeader_t),
243 (void*)payloadAligned,
244 (void*)&IOPFrameBuffer[IOPFrameBufferWrPtr * NETMAN_MAX_FRAME_SIZE],
245 (length + unaligned + 15) & ~15)) == 0){ };
246 } else {
247 //Record the frame length.
248 bd->length = length;
249 bd->offset = unaligned;
250
251 //Normal DMA transfer
252 dmat[0].src = (void*)payloadAligned;
253 dmat[0].dest = (void*)&IOPFrameBuffer[IOPFrameBufferWrPtr * NETMAN_MAX_FRAME_SIZE];
254 dmat[0].size = (length + unaligned + 15) & ~15;
255 dmat[0].attr = 0;
256 dmat[1].src = (void*)&FrameBufferStatus[IOPFrameBufferWrPtr];
257 dmat[1].dest = (void*)&IOPFrameBufferStatus[IOPFrameBufferWrPtr];
258 dmat[1].size = sizeof(struct NetManBD);
259 dmat[1].attr = 0;
260
261 while((dmat_id = SifSetDma(dmat, 2)) == 0){ };
262 }
263
264 //Increase write pointer by one position.
265 IOPFrameBufferWrPtr = (IOPFrameBufferWrPtr + 1) % NETMAN_RPC_BLOCK_SIZE;
266
267 if((length = NetManTxPacketAfter(&payload)) > 0)
268 { //Write back the cache of the next packet, while waiting.
269 unaligned = (int)((u32)payload & 15);
270 unalignedCache = (int)((u32)payload & 63);
271 payloadAligned = (void*)((u32)payload & ~15);
272 payloadCacheAligned = (void*)((u32)payload & ~63);
273 SifWriteBackDCache(payloadCacheAligned, (length + unalignedCache + 63) & ~63);
274 }
275
276 NumTx++;
277
278 while(SifDmaStat(dmat_id) >= 0){ };
279 NetManTxPacketDeQ();
280 } while(length > 0);
281
282 IsProcessingTx = 0;
283 }
284 }
285}
286
287void NetManRpcNetIFXmit(void)
288{
289 if(!IsProcessingTx)
290 WakeupThread(NETMAN_Tx_threadID);
291}
292
293int NetManSetMainIF(const char *name)
294{
295 int result;
296
297 if (!IsInitialized)
298 return -1;
299
300 WaitSema(NetManIOSemaID);
301
302 strncpy(TransmitBuffer.netifName, name, NETMAN_NETIF_NAME_MAX_LEN);
303 TransmitBuffer.netifName[NETMAN_NETIF_NAME_MAX_LEN-1] = '\0';
304 if((result=SifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_SET_MAIN_NETIF, 0, &TransmitBuffer, NETMAN_NETIF_NAME_MAX_LEN, &ReceiveBuffer, sizeof(s32), NULL, NULL))>=0)
305 result=ReceiveBuffer.result;
306
307 SignalSema(NetManIOSemaID);
308
309 return result;
310}
311
312int NetManQueryMainIF(char *name)
313{
314 int result;
315
316 if (!IsInitialized)
317 return -1;
318
319 WaitSema(NetManIOSemaID);
320
321 if((result=SifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_QUERY_MAIN_NETIF, 0, NULL, 0, &ReceiveBuffer, sizeof(struct NetManQueryMainNetIFResult), NULL, NULL))>=0)
322 {
323 if((result=ReceiveBuffer.QueryMainNetIFResult.result) == 0)
324 {
325 strncpy(name, ReceiveBuffer.QueryMainNetIFResult.name, NETMAN_NETIF_NAME_MAX_LEN);
326 name[NETMAN_NETIF_NAME_MAX_LEN-1] = '\0';
327 }
328 }
329
330 SignalSema(NetManIOSemaID);
331
332 return result;
333}
334
335int NetManSetLinkMode(int mode)
336{
337 int result;
338
339 if (!IsInitialized)
340 return -1;
341
342 WaitSema(NetManIOSemaID);
343
344 TransmitBuffer.mode = mode;
345 if((result=SifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_SET_LINK_MODE, 0, &TransmitBuffer, sizeof(s32), &ReceiveBuffer, sizeof(s32), NULL, NULL))>=0)
346 result=ReceiveBuffer.result;
347
348 SignalSema(NetManIOSemaID);
349
350 return result;
351}
#define ENOMEM
Definition errno.h:43