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